/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release
237.2.122 by Teddy Hogeborn
* plugins-runner.c (main): Bug fix: Close config file.
1
/*  -*- coding: utf-8; mode: c; mode: orgtbl -*- */
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
2
/*
3
 * Mandos plugin runner - Run Mandos plugins
4
 *
237.2.9 by Teddy Hogeborn
* README: Update copyright year; add "2009".
5
 * Copyright © 2008,2009 Teddy Hogeborn
6
 * Copyright © 2008,2009 Björn Påhlsson
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
7
 * 
8
 * This program is free software: you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License as
10
 * published by the Free Software Foundation, either version 3 of the
11
 * License, or (at your option) any later version.
12
 * 
13
 * This program is distributed in the hope that it will be useful, but
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16
 * General Public License for more details.
17
 * 
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program.  If not, see
20
 * <http://www.gnu.org/licenses/>.
21
 * 
28 by Teddy Hogeborn
* server.conf: New file.
22
 * Contact the authors at <mandos@fukt.bsnet.se>.
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
23
 */
24
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
25
#define _GNU_SOURCE		/* TEMP_FAILURE_RETRY(), getline(),
237.2.147 by Teddy Hogeborn
* plugin-runner.c (main): Use the O_CLOEXEC flag, if available, when
26
				   asprintf(), O_CLOEXEC */
24.1.26 by Björn Påhlsson
tally count of used symbols
27
#include <stddef.h>		/* size_t, NULL */
28
#include <stdlib.h>		/* malloc(), exit(), EXIT_FAILURE,
29
				   EXIT_SUCCESS, realloc() */
30
#include <stdbool.h>		/* bool, true, false */
205 by Teddy Hogeborn
* Makefile (PLUGINS, uninstall-client,
31
#include <stdio.h>		/* perror, fileno(), fprintf(),
32
				   stderr, STDOUT_FILENO */
237.2.147 by Teddy Hogeborn
* plugin-runner.c (main): Use the O_CLOEXEC flag, if available, when
33
#include <sys/types.h>	        /* DIR, fdopendir(), stat(), struct
24.1.26 by Björn Påhlsson
tally count of used symbols
34
				   stat, waitpid(), WIFEXITED(),
35
				   WEXITSTATUS(), wait(), pid_t,
36
				   uid_t, gid_t, getuid(), getgid(),
37
				   dirfd() */
38
#include <sys/select.h>		/* fd_set, select(), FD_ZERO(),
39
				   FD_SET(), FD_ISSET(), FD_CLR */
40
#include <sys/wait.h>		/* wait(), waitpid(), WIFEXITED(),
237.2.119 by Teddy Hogeborn
* plugin-runner.c (main): When a plugin is killed by a signal, show
41
				   WEXITSTATUS(), WTERMSIG(),
42
				   WCOREDUMP() */
24.1.26 by Björn Påhlsson
tally count of used symbols
43
#include <sys/stat.h>		/* struct stat, stat(), S_ISREG() */
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
44
#include <iso646.h>		/* and, or, not */
237.2.147 by Teddy Hogeborn
* plugin-runner.c (main): Use the O_CLOEXEC flag, if available, when
45
#include <dirent.h>		/* DIR, struct dirent, fdopendir(),
24.1.26 by Björn Påhlsson
tally count of used symbols
46
				   readdir(), closedir(), dirfd() */
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
47
#include <unistd.h>		/* struct stat, stat(), S_ISREG(),
24.1.26 by Björn Påhlsson
tally count of used symbols
48
				   fcntl(), setuid(), setgid(),
49
				   F_GETFD, F_SETFD, FD_CLOEXEC,
50
				   access(), pipe(), fork(), close()
205 by Teddy Hogeborn
* Makefile (PLUGINS, uninstall-client,
51
				   dup2(), STDOUT_FILENO, _exit(),
24.1.26 by Björn Påhlsson
tally count of used symbols
52
				   execv(), write(), read(),
53
				   close() */
54
#include <fcntl.h>		/* fcntl(), F_GETFD, F_SETFD,
55
				   FD_CLOEXEC */
237.2.119 by Teddy Hogeborn
* plugin-runner.c (main): When a plugin is killed by a signal, show
56
#include <string.h>		/* strsep, strlen(), asprintf(),
57
				   strsignal() */
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
58
#include <errno.h>		/* errno */
24.1.26 by Björn Påhlsson
tally count of used symbols
59
#include <argp.h>		/* struct argp_option, struct
60
				   argp_state, struct argp,
61
				   argp_parse(), ARGP_ERR_UNKNOWN,
102 by Teddy Hogeborn
* plugin-runner.c (process): Set "completed" and "status" as volatile.
62
				   ARGP_KEY_END, ARGP_KEY_ARG,
63
				   error_t */
24.1.26 by Björn Påhlsson
tally count of used symbols
64
#include <signal.h> 		/* struct sigaction, sigemptyset(),
65
				   sigaddset(), sigaction(),
66
				   sigprocmask(), SIG_BLOCK, SIGCHLD,
237.2.71 by Teddy Hogeborn
* plugin-runner.c: Comment change.
67
				   SIG_UNBLOCK, kill(), sig_atomic_t
68
				*/
24.1.26 by Björn Påhlsson
tally count of used symbols
69
#include <errno.h>		/* errno, EBADF */
237.2.74 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
70
#include <inttypes.h>		/* intmax_t, PRIdMAX, strtoimax() */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
71
#include <sysexits.h>		/* EX_OSERR, EX_USAGE */
13 by Björn Påhlsson
Added following support:
72
37 by Teddy Hogeborn
Non-tested commit for merge purposes.
73
#define BUFFER_SIZE 256
24.1.69 by Björn Påhlsson
added configfile as a optional argument to plugin-runner
74
75
#define PDIR "/lib/mandos/plugins.d"
76
#define AFILE "/conf/conf.d/mandos/plugin-runner.conf"
37 by Teddy Hogeborn
Non-tested commit for merge purposes.
77
217 by Teddy Hogeborn
* .bzrignore: Added "man" directory (created by "make install-html").
78
const char *argp_program_version = "plugin-runner " VERSION;
24.1.35 by Björn Påhlsson
version 1.0
79
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
80
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
81
typedef struct plugin{
82
  char *name;			/* can be NULL or any plugin name */
83
  char **argv;
84
  int argc;
85
  char **environ;
86
  int envc;
87
  bool disabled;
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
88
  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
89
  /* Variables used for running processes*/
13 by Björn Påhlsson
Added following support:
90
  pid_t pid;
91
  int fd;
92
  char *buffer;
21 by Teddy Hogeborn
* Makefile (CFLAGS): Changed to use $(WARN), $(DEBUG), $(COVERAGE) and
93
  size_t buffer_size;
94
  size_t buffer_length;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
95
  bool eof;
237.2.59 by Teddy Hogeborn
* plugin-runner.c (struct plugin.completed): Changed type to "volatile
96
  volatile sig_atomic_t completed;
237.2.60 by Teddy Hogeborn
* plugin-runner.c (struct plugin.status): Changed type to "int".
97
  int status;
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
98
  struct plugin *next;
99
} plugin;
100
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
101
static plugin *plugin_list = NULL;
102
24.1.90 by Björn Påhlsson
fixed two bugs:
103
/* Gets an existing plugin based on name,
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
104
   or if none is found, creates a new one */
105
static plugin *getplugin(char *name){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
106
  /* Check for existing plugin with that name */
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
107
  for(plugin *p = plugin_list; p != NULL; p = p->next){
108
    if((p->name == name)
109
       or (p->name and name and (strcmp(p->name, name) == 0))){
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
110
      return p;
111
    }
112
  }
113
  /* Create a new plugin */
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
114
  plugin *new_plugin = NULL;
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
115
  do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
116
    new_plugin = malloc(sizeof(plugin));
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
117
  } while(new_plugin == NULL and errno == EINTR);
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
118
  if(new_plugin == NULL){
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
119
    return NULL;
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
120
  }
24.1.62 by Björn Påhlsson
merge + small bugfix
121
  char *copy_name = NULL;
122
  if(name != NULL){
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
123
    do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
124
      copy_name = strdup(name);
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
125
    } while(copy_name == NULL and errno == EINTR);
98 by Teddy Hogeborn
* plugin-runner.c (getplugin): Only copy "name" if not NULL. Free
126
    if(copy_name == NULL){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
127
      int e = errno;
237.2.35 by Teddy Hogeborn
Fix problem found using cppcheck, thanks to George Danchev
128
      free(new_plugin);
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
129
      errno = e;
98 by Teddy Hogeborn
* plugin-runner.c (getplugin): Only copy "name" if not NULL. Free
130
      return NULL;
131
    }
24.1.54 by Björn Påhlsson
plugin-runner
132
  }
24.1.90 by Björn Påhlsson
fixed two bugs:
133
  
237.2.56 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
134
  *new_plugin = (plugin){ .name = copy_name,
135
			  .argc = 1,
136
			  .disabled = false,
137
			  .next = plugin_list };
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
138
  
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
139
  do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
140
    new_plugin->argv = malloc(sizeof(char *) * 2);
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
141
  } while(new_plugin->argv == NULL and errno == EINTR);
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
142
  if(new_plugin->argv == NULL){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
143
    int e = errno;
24.1.62 by Björn Påhlsson
merge + small bugfix
144
    free(copy_name);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
145
    free(new_plugin);
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
146
    errno = e;
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
147
    return NULL;
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
148
  }
24.1.54 by Björn Påhlsson
plugin-runner
149
  new_plugin->argv[0] = copy_name;
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
150
  new_plugin->argv[1] = NULL;
135 by Teddy Hogeborn
* plugin-runner.c (add_environment): Never insert existing environment
151
  
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
152
  do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
153
    new_plugin->environ = malloc(sizeof(char *));
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
154
  } while(new_plugin->environ == NULL and errno == EINTR);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
155
  if(new_plugin->environ == NULL){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
156
    int e = errno;
24.1.62 by Björn Påhlsson
merge + small bugfix
157
    free(copy_name);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
158
    free(new_plugin->argv);
159
    free(new_plugin);
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
160
    errno = e;
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
161
    return NULL;
162
  }
163
  new_plugin->environ[0] = NULL;
135 by Teddy Hogeborn
* plugin-runner.c (add_environment): Never insert existing environment
164
  
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
165
  /* Append the new plugin to the list */
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
166
  plugin_list = new_plugin;
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
167
  return new_plugin;
168
}
169
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
170
/* Helper function for add_argument and add_environment */
171
static bool add_to_char_array(const char *new, char ***array,
172
			      int *len){
173
  /* Resize the pointed-to array to hold one more pointer */
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
174
  do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
175
    *array = realloc(*array, sizeof(char *)
176
		     * (size_t) ((*len) + 2));
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
177
  } while(*array == NULL and errno == EINTR);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
178
  /* Malloc check */
179
  if(*array == NULL){
180
    return false;
181
  }
182
  /* Make a copy of the new string */
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
183
  char *copy;
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
184
  do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
185
    copy = strdup(new);
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
186
  } while(copy == NULL and errno == EINTR);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
187
  if(copy == NULL){
188
    return false;
189
  }
190
  /* Insert the copy */
191
  (*array)[*len] = copy;
192
  (*len)++;
193
  /* Add a new terminating NULL pointer to the last element */
194
  (*array)[*len] = NULL;
195
  return true;
196
}
197
198
/* Add to a plugin's argument vector */
199
static bool add_argument(plugin *p, const char *arg){
200
  if(p == NULL){
201
    return false;
202
  }
203
  return add_to_char_array(arg, &(p->argv), &(p->argc));
204
}
205
206
/* Add to a plugin's environment */
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
207
static bool add_environment(plugin *p, const char *def, bool replace){
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
208
  if(p == NULL){
209
    return false;
210
  }
135 by Teddy Hogeborn
* plugin-runner.c (add_environment): Never insert existing environment
211
  /* namelen = length of name of environment variable */
212
  size_t namelen = (size_t)(strchrnul(def, '=') - def);
213
  /* Search for this environment variable */
214
  for(char **e = p->environ; *e != NULL; e++){
24.1.90 by Björn Påhlsson
fixed two bugs:
215
    if(strncmp(*e, def, namelen + 1) == 0){
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
216
      /* It already exists */
217
      if(replace){
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
218
	char *new;
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
219
	do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
220
	  new = realloc(*e, strlen(def) + 1);
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
221
	} while(new == NULL and errno == EINTR);
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
222
	if(new == NULL){
223
	  return false;
224
	}
225
	*e = new;
226
	strcpy(*e, def);
227
      }
135 by Teddy Hogeborn
* plugin-runner.c (add_environment): Never insert existing environment
228
      return true;
229
    }
230
  }
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
231
  return add_to_char_array(def, &(p->environ), &(p->envc));
232
}
233
32 by Teddy Hogeborn
* plugins.d/plugbasedclient.c (set_cloexec_flag): New function.
234
/*
235
 * Based on the example in the GNU LibC manual chapter 13.13 "File
236
 * Descriptor Flags".
237.2.122 by Teddy Hogeborn
* plugins-runner.c (main): Bug fix: Close config file.
237
 | [[info:libc:Descriptor%20Flags][File Descriptor Flags]] |
32 by Teddy Hogeborn
* plugins.d/plugbasedclient.c (set_cloexec_flag): New function.
238
 */
187 by Teddy Hogeborn
* debian/mandos-client.README.Debian: Document "eth0" default and how
239
static int set_cloexec_flag(int fd){
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
240
  int ret = (int)TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD, 0));
32 by Teddy Hogeborn
* plugins.d/plugbasedclient.c (set_cloexec_flag): New function.
241
  /* If reading the flags failed, return error indication now. */
242
  if(ret < 0){
243
    return ret;
244
  }
245
  /* Store modified flag word in the descriptor. */
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
246
  return (int)TEMP_FAILURE_RETRY(fcntl(fd, F_SETFD,
247
				       ret | FD_CLOEXEC));
32 by Teddy Hogeborn
* plugins.d/plugbasedclient.c (set_cloexec_flag): New function.
248
}
249
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
250
102 by Teddy Hogeborn
* plugin-runner.c (process): Set "completed" and "status" as volatile.
251
/* Mark processes as completed when they exit, and save their exit
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
252
   status. */
187 by Teddy Hogeborn
* debian/mandos-client.README.Debian: Document "eth0" default and how
253
static void handle_sigchld(__attribute__((unused)) int sig){
237.2.61 by Teddy Hogeborn
* plugin-runner.c (handle_sigchld): Bug fix: Save and restore "errno".
254
  int old_errno = errno;
24.1.65 by Björn Påhlsson
* plugin-runner.c (handle_sigchld): Loop until all exited children
255
  while(true){
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
256
    plugin *proc = plugin_list;
24.1.65 by Björn Påhlsson
* plugin-runner.c (handle_sigchld): Loop until all exited children
257
    int status;
258
    pid_t pid = waitpid(-1, &status, WNOHANG);
259
    if(pid == 0){
102 by Teddy Hogeborn
* plugin-runner.c (process): Set "completed" and "status" as volatile.
260
      /* Only still running child processes */
24.1.65 by Björn Påhlsson
* plugin-runner.c (handle_sigchld): Loop until all exited children
261
      break;
262
    }
263
    if(pid == -1){
237.2.58 by Teddy Hogeborn
* plugin-runner.c (handle_sigchld): Clarify logic.
264
      if(errno == ECHILD){
265
	/* No child processes */
266
	break;
24.1.65 by Björn Påhlsson
* plugin-runner.c (handle_sigchld): Loop until all exited children
267
      }
237.2.58 by Teddy Hogeborn
* plugin-runner.c (handle_sigchld): Clarify logic.
268
      perror("waitpid");
24.1.65 by Björn Påhlsson
* plugin-runner.c (handle_sigchld): Loop until all exited children
269
    }
24.1.90 by Björn Påhlsson
fixed two bugs:
270
    
102 by Teddy Hogeborn
* plugin-runner.c (process): Set "completed" and "status" as volatile.
271
    /* A child exited, find it in process_list */
24.1.65 by Björn Påhlsson
* plugin-runner.c (handle_sigchld): Loop until all exited children
272
    while(proc != NULL and proc->pid != pid){
273
      proc = proc->next;
274
    }
275
    if(proc == NULL){
276
      /* Process not found in process list */
277
      continue;
278
    }
279
    proc->status = status;
237.2.59 by Teddy Hogeborn
* plugin-runner.c (struct plugin.completed): Changed type to "volatile
280
    proc->completed = 1;
24.1.65 by Björn Påhlsson
* plugin-runner.c (handle_sigchld): Loop until all exited children
281
  }
237.2.61 by Teddy Hogeborn
* plugin-runner.c (handle_sigchld): Bug fix: Save and restore "errno".
282
  errno = old_errno;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
283
}
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
284
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
285
/* Prints out a password to stdout */
187 by Teddy Hogeborn
* debian/mandos-client.README.Debian: Document "eth0" default and how
286
static bool print_out_password(const char *buffer, size_t length){
64 by Teddy Hogeborn
* mandos-client.c (print_out_password): Strip trailing '\n'.
287
  ssize_t ret;
288
  for(size_t written = 0; written < length; written += (size_t)ret){
24.1.42 by Björn Påhlsson
Added fallback to mandos-client
289
    ret = TEMP_FAILURE_RETRY(write(STDOUT_FILENO, buffer + written,
290
				   length - written));
291
    if(ret < 0){
292
      return false;
293
    }
294
  }
295
  return true;
296
}
297
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
298
/* Removes and free a plugin from the plugin list */
299
static void free_plugin(plugin *plugin_node){
300
  
301
  for(char **arg = plugin_node->argv; *arg != NULL; arg++){
302
    free(*arg);
303
  }
304
  free(plugin_node->argv);
305
  for(char **env = plugin_node->environ; *env != NULL; env++){
306
    free(*env);
307
  }
308
  free(plugin_node->environ);
309
  free(plugin_node->buffer);
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
310
  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
311
  /* Removes the plugin from the singly-linked list */
312
  if(plugin_node == plugin_list){
313
    /* First one - simple */
314
    plugin_list = plugin_list->next;
315
  } else {
316
    /* Second one or later */
317
    for(plugin *p = plugin_list; p != NULL; p = p->next){
318
      if(p->next == plugin_node){
319
	p->next = plugin_node->next;
320
	break;
321
      }
322
    }
323
  }
324
  
325
  free(plugin_node);
326
}
327
328
static void free_plugin_list(void){
329
  while(plugin_list != NULL){
330
    free_plugin(plugin_list);
98 by Teddy Hogeborn
* plugin-runner.c (getplugin): Only copy "name" if not NULL. Free
331
  }
24.1.54 by Björn Påhlsson
plugin-runner
332
}
333
13 by Björn Påhlsson
Added following support:
334
int main(int argc, char *argv[]){
24.1.69 by Björn Påhlsson
added configfile as a optional argument to plugin-runner
335
  char *plugindir = NULL;
336
  char *argfile = NULL;
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
337
  FILE *conffp;
24.1.5 by Björn Påhlsson
plugbasedclient:
338
  size_t d_name_len;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
339
  DIR *dir = NULL;
13 by Björn Påhlsson
Added following support:
340
  struct dirent *dirst;
341
  struct stat st;
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
342
  fd_set rfds_all;
237.2.74 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
343
  int ret, maxfd = 0;
237.2.17 by Teddy Hogeborn
Eliminate warning on 64-bit systems, thanks to Frans Pop
344
  ssize_t sret;
24.1.6 by Björn Påhlsson
plugbasedclient
345
  uid_t uid = 65534;
346
  gid_t gid = 65534;
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
347
  bool debug = false;
348
  int exitstatus = EXIT_SUCCESS;
24.1.7 by Björn Påhlsson
merge
349
  struct sigaction old_sigchld_action;
350
  struct sigaction sigchld_action = { .sa_handler = handle_sigchld,
351
				      .sa_flags = SA_NOCLDSTOP };
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
352
  char **custom_argv = NULL;
353
  int custom_argc = 0;
354
  
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
355
  /* Establish a signal handler */
356
  sigemptyset(&sigchld_action.sa_mask);
357
  ret = sigaddset(&sigchld_action.sa_mask, SIGCHLD);
24.1.54 by Björn Påhlsson
plugin-runner
358
  if(ret == -1){
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
359
    perror("sigaddset");
24.1.54 by Björn Påhlsson
plugin-runner
360
    exitstatus = EXIT_FAILURE;
361
    goto fallback;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
362
  }
363
  ret = sigaction(SIGCHLD, &sigchld_action, &old_sigchld_action);
24.1.54 by Björn Påhlsson
plugin-runner
364
  if(ret == -1){
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
365
    perror("sigaction");
98 by Teddy Hogeborn
* plugin-runner.c (getplugin): Only copy "name" if not NULL. Free
366
    exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
367
    goto fallback;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
368
  }
369
  
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
370
  /* The options we understand. */
371
  struct argp_option options[] = {
372
    { .name = "global-options", .key = 'g',
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
373
      .arg = "OPTION[,OPTION[,...]]",
374
      .doc = "Options passed to all plugins" },
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
375
    { .name = "global-env", .key = 'G',
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
376
      .arg = "VAR=value",
377
      .doc = "Environment variable passed to all plugins" },
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
378
    { .name = "options-for", .key = 'o',
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
379
      .arg = "PLUGIN:OPTION[,OPTION[,...]]",
380
      .doc = "Options passed only to specified plugin" },
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
381
    { .name = "env-for", .key = 'E',
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
382
      .arg = "PLUGIN:ENV=value",
383
      .doc = "Environment variable passed to specified plugin" },
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
384
    { .name = "disable", .key = 'd',
385
      .arg = "PLUGIN",
386
      .doc = "Disable a specific plugin", .group = 1 },
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
387
    { .name = "enable", .key = 'e',
388
      .arg = "PLUGIN",
389
      .doc = "Enable a specific plugin", .group = 1 },
24.1.5 by Björn Påhlsson
plugbasedclient:
390
    { .name = "plugin-dir", .key = 128,
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
391
      .arg = "DIRECTORY",
392
      .doc = "Specify a different plugin directory", .group = 2 },
24.1.69 by Björn Påhlsson
added configfile as a optional argument to plugin-runner
393
    { .name = "config-file", .key = 129,
394
      .arg = "FILE",
395
      .doc = "Specify a different configuration file", .group = 2 },
396
    { .name = "userid", .key = 130,
397
      .arg = "ID", .flags = 0,
398
      .doc = "User ID the plugins will run as", .group = 3 },
399
    { .name = "groupid", .key = 131,
400
      .arg = "ID", .flags = 0,
401
      .doc = "Group ID the plugins will run as", .group = 3 },
402
    { .name = "debug", .key = 132,
403
      .doc = "Debug mode", .group = 4 },
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
404
    /*
405
     * These reproduce what we would get without ARGP_NO_HELP
406
     */
407
    { .name = "help", .key = '?',
408
      .doc = "Give this help list", .group = -1 },
409
    { .name = "usage", .key = -3,
410
      .doc = "Give a short usage message", .group = -1 },
411
    { .name = "version", .key = 'V',
412
      .doc = "Print program version", .group = -1 },
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
413
    { .name = NULL }
414
  };
415
  
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
416
  error_t parse_opt(int key, char *arg, struct argp_state *state){
417
    errno = 0;
237.2.56 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
418
    switch(key){
237.2.123 by Teddy Hogeborn
* plugin-runner.c (main): Move variables "tmpmax" and "tmp" into
419
      char *tmp;
420
      intmax_t tmpmax;
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
421
    case 'g': 			/* --global-options */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
422
      {
24.1.134 by Björn Påhlsson
plugin-runner: Added support for empty string arguments
423
	char *plugin_option;
424
	while((plugin_option = strsep(&arg, ",")) != NULL){
425
	  if(not add_argument(getplugin(NULL), plugin_option)){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
426
	    break;
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
427
	  }
428
	}
429
      }
430
      break;
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
431
    case 'G':			/* --global-env */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
432
      add_environment(getplugin(NULL), arg, true);
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
433
      break;
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
434
    case 'o':			/* --options-for */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
435
      {
436
	char *option_list = strchr(arg, ':');
437
	if(option_list == NULL){
438
	  argp_error(state, "No colon in \"%s\"", arg);
439
	  errno = EINVAL;
440
	  break;
441
	}
442
	*option_list = '\0';
443
	option_list++;
444
	if(arg[0] == '\0'){
445
	  argp_error(state, "Empty plugin name");
446
	  errno = EINVAL;
447
	  break;
448
	}
449
	char *option;
450
	while((option = strsep(&option_list, ",")) != NULL){
451
	  if(not add_argument(getplugin(arg), option)){
452
	    break;
24.1.50 by Björn Påhlsson
changed from using strtok to strsep
453
	  }
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
454
	}
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
455
      }
456
      break;
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
457
    case 'E':			/* --env-for */
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
458
      {
459
	char *envdef = strchr(arg, ':');
460
	if(envdef == NULL){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
461
	  argp_error(state, "No colon in \"%s\"", arg);
462
	  errno = EINVAL;
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
463
	  break;
464
	}
24.1.92 by Björn Påhlsson
Several memory leaks detected by valgrind fixed
465
	*envdef = '\0';
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
466
	envdef++;
467
	if(arg[0] == '\0'){
468
	  argp_error(state, "Empty plugin name");
469
	  errno = EINVAL;
470
	  break;
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
471
	}
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
472
	add_environment(getplugin(arg), envdef, true);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
473
      }
474
      break;
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
475
    case 'd':			/* --disable */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
476
      {
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
477
	plugin *p = getplugin(arg);
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
478
	if(p != NULL){
479
	  p->disabled = true;
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
480
	}
24.1.5 by Björn Påhlsson
plugbasedclient:
481
      }
482
      break;
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
483
    case 'e':			/* --enable */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
484
      {
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
485
	plugin *p = getplugin(arg);
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
486
	if(p != NULL){
487
	  p->disabled = false;
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
488
	}
489
      }
490
      break;
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
491
    case 128:			/* --plugin-dir */
24.1.92 by Björn Påhlsson
Several memory leaks detected by valgrind fixed
492
      free(plugindir);
24.1.69 by Björn Påhlsson
added configfile as a optional argument to plugin-runner
493
      plugindir = strdup(arg);
24.1.5 by Björn Påhlsson
plugbasedclient:
494
      break;
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
495
    case 129:			/* --config-file */
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
496
      /* This is already done by parse_opt_config_file() */
497
      break;
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
498
    case 130:			/* --userid */
237.2.74 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
499
      tmpmax = strtoimax(arg, &tmp, 10);
500
      if(errno != 0 or tmp == arg or *tmp != '\0'
501
	 or tmpmax != (uid_t)tmpmax){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
502
	argp_error(state, "Bad user ID number: \"%s\", using %"
503
		   PRIdMAX, arg, (intmax_t)uid);
504
	break;
237.2.27 by Teddy Hogeborn
* plugin-runner.c (main): Use "sscanf" instead of "strtol"; using the
505
      }
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
506
      uid = (uid_t)tmpmax;
24.1.6 by Björn Påhlsson
plugbasedclient
507
      break;
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
508
    case 131:			/* --groupid */
237.2.74 by Teddy Hogeborn
Overflows are not detected by sscanf(), so stop using it:
509
      tmpmax = strtoimax(arg, &tmp, 10);
510
      if(errno != 0 or tmp == arg or *tmp != '\0'
511
	 or tmpmax != (gid_t)tmpmax){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
512
	argp_error(state, "Bad group ID number: \"%s\", using %"
513
		   PRIdMAX, arg, (intmax_t)gid);
514
	break;
237.2.27 by Teddy Hogeborn
* plugin-runner.c (main): Use "sscanf" instead of "strtol"; using the
515
      }
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
516
      gid = (gid_t)tmpmax;
24.1.6 by Björn Påhlsson
plugbasedclient
517
      break;
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
518
    case 132:			/* --debug */
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
519
      debug = true;
520
      break;
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
521
      /*
522
       * These reproduce what we would get without ARGP_NO_HELP
523
       */
524
    case '?':			/* --help */
525
      state->flags &= ~(unsigned int)ARGP_NO_EXIT; /* force exit */
526
      argp_state_help(state, state->out_stream, ARGP_HELP_STD_HELP);
527
    case -3:			/* --usage */
528
      state->flags &= ~(unsigned int)ARGP_NO_EXIT; /* force exit */
529
      argp_state_help(state, state->out_stream,
530
		      ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
531
    case 'V':			/* --version */
532
      fprintf(state->out_stream, "%s\n", argp_program_version);
533
      exit(EXIT_SUCCESS);
534
      break;
237.2.27 by Teddy Hogeborn
* plugin-runner.c (main): Use "sscanf" instead of "strtol"; using the
535
/*
536
 * When adding more options before this line, remember to also add a
537
 * "case" to the "parse_opt_config_file" function below.
538
 */
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
539
    case ARGP_KEY_ARG:
178 by Teddy Hogeborn
* initramfs-tools-script: Fix permissions of "/tmp" in initrd.
540
      /* Cryptsetup always passes an argument, which is an empty
541
	 string if "none" was specified in /etc/crypttab.  So if
542
	 argument was empty, we ignore it silently. */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
543
      if(arg[0] == '\0'){
544
	break;
178 by Teddy Hogeborn
* initramfs-tools-script: Fix permissions of "/tmp" in initrd.
545
      }
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
546
    default:
547
      return ARGP_ERR_UNKNOWN;
548
    }
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
549
    return errno;		/* Set to 0 at start */
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
550
  }
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
551
  
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
552
  /* This option parser is the same as parse_opt() above, except it
553
     ignores everything but the --config-file option. */
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
554
  error_t parse_opt_config_file(int key, char *arg,
555
				__attribute__((unused))
237.2.56 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
556
				struct argp_state *state){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
557
    errno = 0;
237.2.56 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
558
    switch(key){
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
559
    case 'g': 			/* --global-options */
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
560
    case 'G':			/* --global-env */
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
561
    case 'o':			/* --options-for */
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
562
    case 'E':			/* --env-for */
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
563
    case 'd':			/* --disable */
138 by Teddy Hogeborn
* plugin-runner.c: Changed short option for "--global-env" to "-G",
564
    case 'e':			/* --enable */
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
565
    case 128:			/* --plugin-dir */
566
      break;
567
    case 129:			/* --config-file */
24.1.92 by Björn Påhlsson
Several memory leaks detected by valgrind fixed
568
      free(argfile);
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
569
      argfile = strdup(arg);
237.2.118 by Teddy Hogeborn
* mandos: White-space fixes only.
570
      break;
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
571
    case 130:			/* --userid */
572
    case 131:			/* --groupid */
573
    case 132:			/* --debug */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
574
    case '?':			/* --help */
575
    case -3:			/* --usage */
576
    case 'V':			/* --version */
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
577
    case ARGP_KEY_ARG:
578
      break;
579
    default:
580
      return ARGP_ERR_UNKNOWN;
581
    }
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
582
    return errno;
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
583
  }
584
  
585
  struct argp argp = { .options = options,
586
		       .parser = parse_opt_config_file,
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
587
		       .args_doc = "",
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
588
		       .doc = "Mandos plugin runner -- Run plugins" };
589
  
237.2.28 by Teddy Hogeborn
* plugin-runner.c (main): Bug fix; do not accept a "d" character after
590
  /* Parse using parse_opt_config_file() in order to get the custom
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
591
     config file location, if any. */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
592
  ret = argp_parse(&argp, argc, argv,
593
		   ARGP_IN_ORDER | ARGP_NO_EXIT | ARGP_NO_HELP,
594
		   NULL, NULL);
595
  switch(ret){
596
  case 0:
597
    break;
598
  case ENOMEM:
599
  default:
600
    errno = ret;
601
    perror("argp_parse");
602
    exitstatus = EX_OSERR;
603
    goto fallback;
604
  case EINVAL:
605
    exitstatus = EX_USAGE;
137 by Teddy Hogeborn
* plugin-runner.c (main/parse_opt): Removed code for "--config-file".
606
    goto fallback;
607
  }
608
  
609
  /* Reset to the normal argument parser */
610
  argp.parser = parse_opt;
611
  
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
612
  /* Open the configfile if available */
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
613
  if(argfile == NULL){
24.1.69 by Björn Påhlsson
added configfile as a optional argument to plugin-runner
614
    conffp = fopen(AFILE, "r");
615
  } else {
616
    conffp = fopen(argfile, "r");
237.2.118 by Teddy Hogeborn
* mandos: White-space fixes only.
617
  }
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
618
  if(conffp != NULL){
619
    char *org_line = NULL;
24.1.54 by Björn Påhlsson
plugin-runner
620
    char *p, *arg, *new_arg, *line;
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
621
    size_t size = 0;
622
    const char whitespace_delims[] = " \r\t\f\v\n";
623
    const char comment_delim[] = "#";
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
624
    
24.1.67 by Björn Påhlsson
transformed a function to a part of main
625
    custom_argc = 1;
626
    custom_argv = malloc(sizeof(char*) * 2);
627
    if(custom_argv == NULL){
628
      perror("malloc");
629
      exitstatus = EXIT_FAILURE;
630
      goto fallback;
631
    }
632
    custom_argv[0] = argv[0];
633
    custom_argv[1] = NULL;
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
634
    
133 by Teddy Hogeborn
* plugin-runner.c: Break a couple of long lines.
635
    /* for each line in the config file, strip whitespace and ignore
636
       commented text */
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
637
    while(true){
638
      sret = getline(&org_line, &size, conffp);
639
      if(sret == -1){
640
	break;
641
      }
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
642
      
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
643
      line = org_line;
644
      arg = strsep(&line, comment_delim);
645
      while((p = strsep(&arg, whitespace_delims)) != NULL){
646
	if(p[0] == '\0'){
647
	  continue;
648
	}
649
	new_arg = strdup(p);
24.1.69 by Björn Påhlsson
added configfile as a optional argument to plugin-runner
650
	if(new_arg == NULL){
651
	  perror("strdup");
652
	  exitstatus = EXIT_FAILURE;
653
	  free(org_line);
654
	  goto fallback;
655
	}
656
	
24.1.67 by Björn Påhlsson
transformed a function to a part of main
657
	custom_argc += 1;
658
	custom_argv = realloc(custom_argv, sizeof(char *)
659
			      * ((unsigned int) custom_argc + 1));
660
	if(custom_argv == NULL){
661
	  perror("realloc");
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
662
	  exitstatus = EXIT_FAILURE;
24.1.67 by Björn Påhlsson
transformed a function to a part of main
663
	  free(org_line);
24.1.54 by Björn Påhlsson
plugin-runner
664
	  goto fallback;
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
665
	}
24.1.67 by Björn Påhlsson
transformed a function to a part of main
666
	custom_argv[custom_argc-1] = new_arg;
237.2.118 by Teddy Hogeborn
* mandos: White-space fixes only.
667
	custom_argv[custom_argc] = NULL;
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
668
      }
669
    }
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
670
    do {
237.2.122 by Teddy Hogeborn
* plugins-runner.c (main): Bug fix: Close config file.
671
      ret = fclose(conffp);
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
672
    } while(ret == EOF and errno == EINTR);
237.2.122 by Teddy Hogeborn
* plugins-runner.c (main): Bug fix: Close config file.
673
    if(ret == EOF){
674
      perror("fclose");
675
      exitstatus = EXIT_FAILURE;
676
      goto fallback;
677
    }
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
678
    free(org_line);
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
679
  } else {
24.1.52 by Björn Påhlsson
merge + minor adjustments
680
    /* Check for harmful errors and go to fallback. Other errors might
681
       not affect opening plugins */
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
682
    if(errno == EMFILE or errno == ENFILE or errno == ENOMEM){
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
683
      perror("fopen");
24.1.8 by Björn Påhlsson
plugbasedclient
684
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
685
      goto fallback;
24.1.8 by Björn Påhlsson
plugbasedclient
686
    }
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
687
  }
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
688
  /* If there were any arguments from the configuration file, pass
689
     them to parser as command line arguments */
24.1.51 by Björn Påhlsson
Added configuration files support for mandos-client
690
  if(custom_argv != NULL){
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
691
    ret = argp_parse(&argp, custom_argc, custom_argv,
692
		     ARGP_IN_ORDER | ARGP_NO_EXIT | ARGP_NO_HELP,
693
		     NULL, NULL);
694
    switch(ret){
695
    case 0:
696
      break;
697
    case ENOMEM:
698
    default:
699
      errno = ret;
700
      perror("argp_parse");
701
      exitstatus = EX_OSERR;
702
      goto fallback;
703
    case EINVAL:
704
      exitstatus = EX_CONFIG;
24.1.54 by Björn Påhlsson
plugin-runner
705
      goto fallback;
24.1.26 by Björn Påhlsson
tally count of used symbols
706
    }
24.1.8 by Björn Påhlsson
plugbasedclient
707
  }
708
  
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
709
  /* Parse actual command line arguments, to let them override the
710
     config file */
237.2.157 by Teddy Hogeborn
Convert some programs to use the exit codes from <sysexits.h>. Change
711
  ret = argp_parse(&argp, argc, argv,
712
		   ARGP_IN_ORDER | ARGP_NO_EXIT | ARGP_NO_HELP,
713
		   NULL, NULL);
714
  switch(ret){
715
  case 0:
716
    break;
717
  case ENOMEM:
718
  default:
719
    errno = ret;
720
    perror("argp_parse");
721
    exitstatus = EX_OSERR;
722
    goto fallback;
723
  case EINVAL:
724
    exitstatus = EX_USAGE;
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
725
    goto fallback;
726
  }
727
  
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
728
  if(debug){
729
    for(plugin *p = plugin_list; p != NULL; p=p->next){
730
      fprintf(stderr, "Plugin: %s has %d arguments\n",
32 by Teddy Hogeborn
* plugins.d/plugbasedclient.c (set_cloexec_flag): New function.
731
	      p->name ? p->name : "Global", p->argc - 1);
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
732
      for(char **a = p->argv; *a != NULL; a++){
733
	fprintf(stderr, "\tArg: %s\n", *a);
734
      }
237.2.31 by Teddy Hogeborn
Fixes for sscanf usage:
735
      fprintf(stderr, "...and %d environment variables\n", p->envc);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
736
      for(char **a = p->environ; *a != NULL; a++){
737
	fprintf(stderr, "\t%s\n", *a);
738
      }
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
739
    }
740
  }
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
741
  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
742
  /* Strip permissions down to nobody */
237.2.62 by Teddy Hogeborn
* plugin-runner.c (main): Bug fix: Do setgid before setuid.
743
  setgid(gid);
744
  if(ret == -1){
745
    perror("setgid");
746
  }
24.1.6 by Björn Påhlsson
plugbasedclient
747
  ret = setuid(uid);
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
748
  if(ret == -1){
24.1.6 by Björn Påhlsson
plugbasedclient
749
    perror("setuid");
750
  }
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
751
  
237.2.147 by Teddy Hogeborn
* plugin-runner.c (main): Use the O_CLOEXEC flag, if available, when
752
  /* Open plugin directory with close_on_exec flag */
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
753
  {
237.2.147 by Teddy Hogeborn
* plugin-runner.c (main): Use the O_CLOEXEC flag, if available, when
754
    int dir_fd = -1;
755
    if(plugindir == NULL){
756
      dir_fd = open(PDIR, O_RDONLY |
757
#ifdef O_CLOEXEC
758
		    O_CLOEXEC
759
#else  /* not O_CLOEXEC */
760
		    0
761
#endif	/* not O_CLOEXEC */
762
		    );
763
    } else {
764
      dir_fd = open(plugindir, O_RDONLY |
765
#ifdef O_CLOEXEC
766
		    O_CLOEXEC
767
#else  /* not O_CLOEXEC */
768
		    0
769
#endif	/* not O_CLOEXEC */
770
		    );
771
    }
772
    if(dir_fd == -1){
773
      perror("Could not open plugin dir");
774
      exitstatus = EXIT_FAILURE;
775
      goto fallback;
776
    }
777
    
778
#ifndef O_CLOEXEC
779
  /* Set the FD_CLOEXEC flag on the directory */
780
    ret = set_cloexec_flag(dir_fd);
781
    if(ret < 0){
782
      perror("set_cloexec_flag");
783
      TEMP_FAILURE_RETRY(close(dir_fd));
784
      exitstatus = EXIT_FAILURE;
785
      goto fallback;
786
    }
787
#endif	/* O_CLOEXEC */
788
    
789
    dir = fdopendir(dir_fd);
790
    if(dir == NULL){
791
      perror("Could not open plugin dir");
792
      TEMP_FAILURE_RETRY(close(dir_fd));
793
      exitstatus = EXIT_FAILURE;
794
      goto fallback;
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
795
    }
796
  }
24.1.1 by Björn Påhlsson
Added syntax and support for plugbasedclient arguments and how they
797
  
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
798
  FD_ZERO(&rfds_all);
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
799
  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
800
  /* Read and execute any executable in the plugin directory*/
13 by Björn Påhlsson
Added following support:
801
  while(true){
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
802
    do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
803
      dirst = readdir(dir);
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
804
    } while(dirst == NULL and errno == EINTR);
13 by Björn Påhlsson
Added following support:
805
    
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
806
    /* All directory entries have been processed */
13 by Björn Påhlsson
Added following support:
807
    if(dirst == NULL){
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
808
      if(errno == EBADF){
24.1.26 by Björn Påhlsson
tally count of used symbols
809
	perror("readdir");
810
	exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
811
	goto fallback;
24.1.26 by Björn Påhlsson
tally count of used symbols
812
      }
13 by Björn Påhlsson
Added following support:
813
      break;
814
    }
815
    
816
    d_name_len = strlen(dirst->d_name);
817
    
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
818
    /* Ignore dotfiles, backup files and other junk */
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
819
    {
820
      bool bad_name = false;
821
      
822
      const char const *bad_prefixes[] = { ".", "#", NULL };
823
      
824
      const char const *bad_suffixes[] = { "~", "#", ".dpkg-new",
825
					   ".dpkg-old",
236 by Teddy Hogeborn
* initramfs-tools-hook: Also ignore plugins named "*.dpkg-bak".
826
					   ".dpkg-bak",
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
827
					   ".dpkg-divert", NULL };
828
      for(const char **pre = bad_prefixes; *pre != NULL; pre++){
829
	size_t pre_len = strlen(*pre);
830
	if((d_name_len >= pre_len)
831
	   and strncmp((dirst->d_name), *pre, pre_len) == 0){
832
	  if(debug){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
833
	    fprintf(stderr, "Ignoring plugin dir entry \"%s\""
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
834
		    " with bad prefix %s\n", dirst->d_name, *pre);
835
	  }
836
	  bad_name = true;
837
	  break;
838
	}
839
      }
840
      if(bad_name){
841
	continue;
842
      }
843
      for(const char **suf = bad_suffixes; *suf != NULL; suf++){
844
	size_t suf_len = strlen(*suf);
845
	if((d_name_len >= suf_len)
846
	   and (strcmp((dirst->d_name)+d_name_len-suf_len, *suf)
847
		== 0)){
848
	  if(debug){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
849
	    fprintf(stderr, "Ignoring plugin dir entry \"%s\""
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
850
		    " with bad suffix %s\n", dirst->d_name, *suf);
851
	  }
852
	  bad_name = true;
853
	  break;
854
	}
855
      }
856
      
857
      if(bad_name){
858
	continue;
859
      }
13 by Björn Påhlsson
Added following support:
860
    }
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
861
    
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
862
    char *filename;
169 by Teddy Hogeborn
* plugin-runner.c (main): Bug fix: use built-in default value if
863
    if(plugindir == NULL){
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
864
      ret = (int)TEMP_FAILURE_RETRY(asprintf(&filename, PDIR "/%s",
865
					     dirst->d_name));
169 by Teddy Hogeborn
* plugin-runner.c (main): Bug fix: use built-in default value if
866
    } else {
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
867
      ret = (int)TEMP_FAILURE_RETRY(asprintf(&filename, "%s/%s",
868
					     plugindir,
869
					     dirst->d_name));
169 by Teddy Hogeborn
* plugin-runner.c (main): Bug fix: use built-in default value if
870
    }
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
871
    if(ret < 0){
872
      perror("asprintf");
24.1.46 by Björn Påhlsson
mandos-client
873
      continue;
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
874
    }
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
875
    
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
876
    ret = (int)TEMP_FAILURE_RETRY(stat(filename, &st));
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
877
    if(ret == -1){
24.1.26 by Björn Påhlsson
tally count of used symbols
878
      perror("stat");
24.1.46 by Björn Påhlsson
mandos-client
879
      free(filename);
880
      continue;
24.1.26 by Björn Påhlsson
tally count of used symbols
881
    }
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
882
    
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
883
    /* Ignore non-executable files */
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
884
    if(not S_ISREG(st.st_mode)
885
       or (TEMP_FAILURE_RETRY(access(filename, X_OK)) != 0)){
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
886
      if(debug){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
887
	fprintf(stderr, "Ignoring plugin dir entry \"%s\""
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
888
		" with bad type or mode\n", filename);
889
      }
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
890
      free(filename);
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
891
      continue;
892
    }
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
893
    
894
    plugin *p = getplugin(dirst->d_name);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
895
    if(p == NULL){
896
      perror("getplugin");
897
      free(filename);
898
      continue;
899
    }
900
    if(p->disabled){
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
901
      if(debug){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
902
	fprintf(stderr, "Ignoring disabled plugin \"%s\"\n",
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
903
		dirst->d_name);
904
      }
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
905
      free(filename);
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
906
      continue;
907
    }
32 by Teddy Hogeborn
* plugins.d/plugbasedclient.c (set_cloexec_flag): New function.
908
    {
909
      /* Add global arguments to argument list for this plugin */
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
910
      plugin *g = getplugin(NULL);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
911
      if(g != NULL){
912
	for(char **a = g->argv + 1; *a != NULL; a++){
913
	  if(not add_argument(p, *a)){
914
	    perror("add_argument");
915
	  }
916
	}
917
	/* Add global environment variables */
918
	for(char **e = g->environ; *e != NULL; e++){
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
919
	  if(not add_environment(p, *e, false)){
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
920
	    perror("add_environment");
921
	  }
922
	}
923
      }
924
    }
925
    /* If this plugin has any environment variables, we will call
926
       using execve and need to duplicate the environment from this
927
       process, too. */
928
    if(p->environ[0] != NULL){
929
      for(char **e = environ; *e != NULL; e++){
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
930
	if(not add_environment(p, *e, false)){
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
931
	  perror("add_environment");
932
	}
933
      }
934
    }
935
    
98 by Teddy Hogeborn
* plugin-runner.c (getplugin): Only copy "name" if not NULL. Free
936
    int pipefd[2];
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
937
    ret = (int)TEMP_FAILURE_RETRY(pipe(pipefd));
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
938
    if(ret == -1){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
939
      perror("pipe");
940
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
941
      goto fallback;
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
942
    }
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
943
    /* Ask OS to automatic close the pipe on exec */
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
944
    ret = set_cloexec_flag(pipefd[0]);
945
    if(ret < 0){
946
      perror("set_cloexec_flag");
947
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
948
      goto fallback;
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
949
    }
950
    ret = set_cloexec_flag(pipefd[1]);
951
    if(ret < 0){
952
      perror("set_cloexec_flag");
953
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
954
      goto fallback;
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
955
    }
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
956
    /* Block SIGCHLD until process is safely in process list */
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
957
    ret = (int)TEMP_FAILURE_RETRY(sigprocmask(SIG_BLOCK,
958
					      &sigchld_action.sa_mask,
959
					      NULL));
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
960
    if(ret < 0){
961
      perror("sigprocmask");
962
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
963
      goto fallback;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
964
    }
136 by Teddy Hogeborn
* plugin-runner.c (add_environment): Override existing environment
965
    /* Starting a new process to be watched */
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
966
    pid_t pid;
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
967
    do {
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
968
      pid = fork();
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
969
    } while(pid == -1 and errno == EINTR);
24.1.46 by Björn Påhlsson
mandos-client
970
    if(pid == -1){
971
      perror("fork");
972
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
973
      goto fallback;
24.1.46 by Björn Påhlsson
mandos-client
974
    }
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
975
    if(pid == 0){
976
      /* this is the child process */
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
977
      ret = sigaction(SIGCHLD, &old_sigchld_action, NULL);
978
      if(ret < 0){
979
	perror("sigaction");
980
	_exit(EXIT_FAILURE);
981
      }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
982
      ret = sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask, NULL);
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
983
      if(ret < 0){
984
	perror("sigprocmask");
985
	_exit(EXIT_FAILURE);
986
      }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
987
      
24.1.26 by Björn Påhlsson
tally count of used symbols
988
      ret = dup2(pipefd[1], STDOUT_FILENO); /* replace our stdout */
989
      if(ret == -1){
990
	perror("dup2");
991
	_exit(EXIT_FAILURE);
992
      }
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
993
      
994
      if(dirfd(dir) < 0){
995
	/* If dir has no file descriptor, we could not set FD_CLOEXEC
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
996
	   above and must now close it manually here. */
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
997
	closedir(dir);
33 by Teddy Hogeborn
* plugins.d/plugbasedclient.c (main): Close the pipe fd after dup2:ing
998
      }
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
999
      if(p->environ[0] == NULL){
1000
	if(execv(filename, p->argv) < 0){
1001
	  perror("execv");
1002
	  _exit(EXIT_FAILURE);
1003
	}
1004
      } else {
1005
	if(execve(filename, p->argv, p->environ) < 0){
1006
	  perror("execve");
1007
	  _exit(EXIT_FAILURE);
1008
	}
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
1009
      }
1010
      /* no return */
1011
    }
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1012
    /* Parent process */
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
1013
    TEMP_FAILURE_RETRY(close(pipefd[1])); /* Close unused write end of
1014
					     pipe */
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1015
    free(filename);
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1016
    plugin *new_plugin = getplugin(dirst->d_name);
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1017
    if(new_plugin == NULL){
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1018
      perror("getplugin");
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
1019
      ret = (int)(TEMP_FAILURE_RETRY
1020
		  (sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask,
1021
			       NULL)));
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1022
      if(ret < 0){
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1023
        perror("sigprocmask");
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1024
      }
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
1025
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
1026
      goto fallback;
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
1027
    }
1028
    
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1029
    new_plugin->pid = pid;
1030
    new_plugin->fd = pipefd[0];
1031
    
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1032
    /* Unblock SIGCHLD so signal handler can be run if this process
1033
       has already completed */
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
1034
    ret = (int)TEMP_FAILURE_RETRY(sigprocmask(SIG_UNBLOCK,
1035
					      &sigchld_action.sa_mask,
1036
					      NULL));
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1037
    if(ret < 0){
1038
      perror("sigprocmask");
1039
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
1040
      goto fallback;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1041
    }
1042
    
237.2.141 by Teddy Hogeborn
* mandos (MandosServer): Fixed doc string.
1043
    FD_SET(new_plugin->fd, &rfds_all); /* Spurious warning from
1044
					  -Wconversion */
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1045
    
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1046
    if(maxfd < new_plugin->fd){
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1047
      maxfd = new_plugin->fd;
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
1048
    }
13 by Björn Påhlsson
Added following support:
1049
  }
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1050
  
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
1051
  TEMP_FAILURE_RETRY(closedir(dir));
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1052
  dir = NULL;
24.1.132 by Björn Påhlsson
Fixed a bug in fallback handling
1053
  free_plugin(getplugin(NULL));
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
1054
  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1055
  for(plugin *p = plugin_list; p != NULL; p = p->next){
1056
    if(p->pid != 0){
1057
      break;
1058
    }
1059
    if(p->next == NULL){
1060
      fprintf(stderr, "No plugin processes started. Incorrect plugin"
1061
	      " directory?\n");
1062
      free_plugin_list();
1063
    }
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1064
  }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
1065
  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1066
  /* Main loop while running plugins exist */
1067
  while(plugin_list){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1068
    fd_set rfds = rfds_all;
1069
    int select_ret = select(maxfd+1, &rfds, NULL, NULL, NULL);
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
1070
    if(select_ret == -1 and errno != EINTR){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1071
      perror("select");
1072
      exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
1073
      goto fallback;
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1074
    }
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1075
    /* OK, now either a process completed, or something can be read
1076
       from one of them */
24.1.92 by Björn Påhlsson
Several memory leaks detected by valgrind fixed
1077
    for(plugin *proc = plugin_list; proc != NULL;){
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1078
      /* Is this process completely done? */
237.2.60 by Teddy Hogeborn
* plugin-runner.c (struct plugin.status): Changed type to "int".
1079
      if(proc->completed and proc->eof){
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1080
	/* Only accept the plugin output if it exited cleanly */
1081
	if(not WIFEXITED(proc->status)
1082
	   or WEXITSTATUS(proc->status) != 0){
1083
	  /* Bad exit by plugin */
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1084
	  
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1085
	  if(debug){
1086
	    if(WIFEXITED(proc->status)){
237.2.64 by Teddy Hogeborn
* plugin-runner.c (main): If debugging, print name of failed plugins.
1087
	      fprintf(stderr, "Plugin %s [%" PRIdMAX "] exited with"
1088
		      " status %d\n", proc->name,
1089
		      (intmax_t) (proc->pid),
60 by Teddy Hogeborn
* mandos-client.c (main): Cast pid_t to unsigned int before printing.
1090
		      WEXITSTATUS(proc->status));
237.2.56 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1091
	    } else if(WIFSIGNALED(proc->status)){
237.2.64 by Teddy Hogeborn
* plugin-runner.c (main): If debugging, print name of failed plugins.
1092
	      fprintf(stderr, "Plugin %s [%" PRIdMAX "] killed by"
237.2.119 by Teddy Hogeborn
* plugin-runner.c (main): When a plugin is killed by a signal, show
1093
		      " signal %d: %s\n", proc->name,
237.2.64 by Teddy Hogeborn
* plugin-runner.c (main): If debugging, print name of failed plugins.
1094
		      (intmax_t) (proc->pid),
237.2.119 by Teddy Hogeborn
* plugin-runner.c (main): When a plugin is killed by a signal, show
1095
		      WTERMSIG(proc->status),
1096
		      strsignal(WTERMSIG(proc->status)));
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1097
	    } else if(WCOREDUMP(proc->status)){
237.2.64 by Teddy Hogeborn
* plugin-runner.c (main): If debugging, print name of failed plugins.
1098
	      fprintf(stderr, "Plugin %s [%" PRIdMAX "] dumped"
1099
		      " core\n", proc->name, (intmax_t) (proc->pid));
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1100
	    }
1101
	  }
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1102
	  
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1103
	  /* Remove the plugin */
237.2.141 by Teddy Hogeborn
* mandos (MandosServer): Fixed doc string.
1104
	  FD_CLR(proc->fd, &rfds_all); /* Spurious warning from
1105
					  -Wconversion */
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1106
	  
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1107
	  /* Block signal while modifying process_list */
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
1108
	  ret = (int)TEMP_FAILURE_RETRY(sigprocmask
1109
					(SIG_BLOCK,
1110
					 &sigchld_action.sa_mask,
1111
					 NULL));
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1112
	  if(ret < 0){
1113
	    perror("sigprocmask");
1114
	    exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
1115
	    goto fallback;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1116
	  }
24.1.92 by Björn Påhlsson
Several memory leaks detected by valgrind fixed
1117
	  
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
1118
	  plugin *next_plugin = proc->next;
1119
	  free_plugin(proc);
1120
	  proc = next_plugin;
1121
	  
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1122
	  /* We are done modifying process list, so unblock signal */
237.2.130 by Teddy Hogeborn
* init.d-mandos: Bug fix: Correct the LSB header.
1123
	  ret = (int)(TEMP_FAILURE_RETRY
1124
		      (sigprocmask(SIG_UNBLOCK,
1125
				   &sigchld_action.sa_mask, NULL)));
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1126
	  if(ret < 0){
1127
	    perror("sigprocmask");
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1128
	    exitstatus = EXIT_FAILURE;
1129
	    goto fallback;
1130
	  }
1131
	  
1132
	  if(plugin_list == NULL){
1133
	    break;
1134
	  }
24.1.92 by Björn Påhlsson
Several memory leaks detected by valgrind fixed
1135
	  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1136
	  continue;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1137
	}
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1138
	
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1139
	/* This process exited nicely, so print its buffer */
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
1140
	
102 by Teddy Hogeborn
* plugin-runner.c (process): Set "completed" and "status" as volatile.
1141
	bool bret = print_out_password(proc->buffer,
1142
				       proc->buffer_length);
24.1.42 by Björn Påhlsson
Added fallback to mandos-client
1143
	if(not bret){
1144
	  perror("print_out_password");
1145
	  exitstatus = EXIT_FAILURE;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1146
	}
24.1.54 by Björn Påhlsson
plugin-runner
1147
	goto fallback;
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1148
      }
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1149
      
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1150
      /* This process has not completed.  Does it have any output? */
237.2.141 by Teddy Hogeborn
* mandos (MandosServer): Fixed doc string.
1151
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){ /* Spurious
1152
							 warning from
1153
							 -Wconversion */
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1154
	/* This process had nothing to say at this time */
24.1.92 by Björn Påhlsson
Several memory leaks detected by valgrind fixed
1155
	proc = proc->next;
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1156
	continue;
1157
      }
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1158
      /* Before reading, make the process' data buffer large enough */
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1159
      if(proc->buffer_length + BUFFER_SIZE > proc->buffer_size){
1160
	proc->buffer = realloc(proc->buffer, proc->buffer_size
1161
			       + (size_t) BUFFER_SIZE);
237.2.29 by Teddy Hogeborn
* plugin-runner.c: Only space changes.
1162
	if(proc->buffer == NULL){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1163
	  perror("malloc");
1164
	  exitstatus = EXIT_FAILURE;
24.1.54 by Björn Påhlsson
plugin-runner
1165
	  goto fallback;
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1166
	}
1167
	proc->buffer_size += BUFFER_SIZE;
1168
      }
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1169
      /* Read from the process */
237.2.125 by Teddy Hogeborn
* plugin-runner.c (getplugin, add_environment, main): Handle EINTR
1170
      sret = TEMP_FAILURE_RETRY(read(proc->fd,
1171
				     proc->buffer
1172
				     + proc->buffer_length,
1173
				     BUFFER_SIZE));
237.2.17 by Teddy Hogeborn
Eliminate warning on 64-bit systems, thanks to Frans Pop
1174
      if(sret < 0){
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1175
	/* Read error from this process; ignore the error */
24.1.92 by Björn Påhlsson
Several memory leaks detected by valgrind fixed
1176
	proc = proc->next;
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1177
	continue;
1178
      }
237.2.17 by Teddy Hogeborn
Eliminate warning on 64-bit systems, thanks to Frans Pop
1179
      if(sret == 0){
34 by Teddy Hogeborn
* plugbasedclient.c (main): Check if plugin dir could be opened. Set
1180
	/* got EOF */
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1181
	proc->eof = true;
1182
      } else {
237.2.17 by Teddy Hogeborn
Eliminate warning on 64-bit systems, thanks to Frans Pop
1183
	proc->buffer_length += (size_t) sret;
13 by Björn Påhlsson
Added following support:
1184
      }
1185
    }
1186
  }
237.2.75 by Teddy Hogeborn
* plugin-runner.c: Whitespace changes only.
1187
  
1188
  
24.1.54 by Björn Påhlsson
plugin-runner
1189
 fallback:
24.1.42 by Björn Påhlsson
Added fallback to mandos-client
1190
  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1191
  if(plugin_list == NULL or exitstatus != EXIT_SUCCESS){
102 by Teddy Hogeborn
* plugin-runner.c (process): Set "completed" and "status" as volatile.
1192
    /* Fallback if all plugins failed, none are found or an error
1193
       occured */
24.1.42 by Björn Påhlsson
Added fallback to mandos-client
1194
    bool bret;
1195
    fprintf(stderr, "Going to fallback mode using getpass(3)\n");
1196
    char *passwordbuffer = getpass("Password: ");
168 by Teddy Hogeborn
* initramfs-tools-hook: Use long options where available. Use only
1197
    size_t len = strlen(passwordbuffer);
1198
    /* Strip trailing newline */
1199
    if(len > 0 and passwordbuffer[len-1] == '\n'){
1200
      passwordbuffer[len-1] = '\0'; /* not strictly necessary */
1201
      len--;
1202
    }
1203
    bret = print_out_password(passwordbuffer, len);
24.1.42 by Björn Påhlsson
Added fallback to mandos-client
1204
    if(not bret){
1205
      perror("print_out_password");
1206
      exitstatus = EXIT_FAILURE;
1207
    }
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1208
  }
24.1.42 by Björn Påhlsson
Added fallback to mandos-client
1209
  
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1210
  /* Restore old signal handler */
24.1.54 by Björn Påhlsson
plugin-runner
1211
  ret = sigaction(SIGCHLD, &old_sigchld_action, NULL);
1212
  if(ret == -1){
1213
    perror("sigaction");
1214
    exitstatus = EXIT_FAILURE;
1215
  }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
1216
  
24.1.54 by Björn Påhlsson
plugin-runner
1217
  if(custom_argv != NULL){
24.1.67 by Björn Påhlsson
transformed a function to a part of main
1218
    for(char **arg = custom_argv+1; *arg != NULL; arg++){
24.1.54 by Björn Påhlsson
plugin-runner
1219
      free(*arg);
78 by Teddy Hogeborn
Add feature to specify custom environment variables for plugins.
1220
    }
24.1.54 by Björn Påhlsson
plugin-runner
1221
    free(custom_argv);
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1222
  }
1223
  
1224
  if(dir != NULL){
1225
    closedir(dir);
1226
  }
1227
  
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
1228
  /* Kill the processes */
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1229
  for(plugin *p = plugin_list; p != NULL; p = p->next){
1230
    if(p->pid != 0){
1231
      close(p->fd);
1232
      ret = kill(p->pid, SIGTERM);
1233
      if(ret == -1 and errno != ESRCH){
1234
	/* Set-uid proccesses might not get closed */
1235
	perror("kill");
1236
      }
24.1.26 by Björn Påhlsson
tally count of used symbols
1237
    }
13 by Björn Påhlsson
Added following support:
1238
  }
1239
  
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1240
  /* Wait for any remaining child processes to terminate */
237.2.126 by Teddy Hogeborn
* plugin-runner.c: Minor stylistic changes.
1241
  do {
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1242
    ret = wait(NULL);
1243
  } while(ret >= 0);
1244
  if(errno != ECHILD){
1245
    perror("wait");
1246
  }
210 by Teddy Hogeborn
* debian/mandos-client.postinst: Change home directory to
1247
  
24.1.76 by Björn Påhlsson
Rearranged so plugins and processes is the same thing
1248
  free_plugin_list();
1249
  
24.1.69 by Björn Påhlsson
added configfile as a optional argument to plugin-runner
1250
  free(plugindir);
1251
  free(argfile);
35 by Teddy Hogeborn
* plugbasedclient.c (struct process): New fields "eof", "completed",
1252
  
31 by Teddy Hogeborn
* plugins.d/plugbasedclient.c: Update include file comments.
1253
  return exitstatus;
13 by Björn Påhlsson
Added following support:
1254
}