/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos-client.c

  • Committer: Teddy Hogeborn
  • Date: 2008-08-11 20:16:35 UTC
  • mfrom: (24.1.45 mandos)
  • Revision ID: teddy@fukt.bsnet.se-20080811201635-1vor0gz43trtily1
Merge.

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
                                   close() */
52
52
#include <fcntl.h>              /* fcntl(), F_GETFD, F_SETFD,
53
53
                                   FD_CLOEXEC */
54
 
#include <string.h>             /* strsep, strlen(), strcpy(),
 
54
#include <string.h>             /* strtok, strlen(), strcpy(),
55
55
                                   strcat() */
56
56
#include <errno.h>              /* errno */
57
57
#include <argp.h>               /* struct argp_option, struct
65
65
#include <errno.h>              /* errno, EBADF */
66
66
 
67
67
#define BUFFER_SIZE 256
68
 
#define CONFFILE "/conf/conf.d/mandos/client.conf"
69
68
 
70
69
const char *argp_program_version = "mandos-client 1.0";
71
70
const char *argp_program_bug_address = "<mandos@fukt.bsnet.se>";
186
185
  return true;
187
186
}
188
187
 
189
 
char ** addcustomargument(char **argv, int *argc, char *arg){
190
 
 
191
 
  if (argv == NULL){
192
 
    *argc = 1;
193
 
    argv = malloc(sizeof(char*) * 2);
194
 
    if(argv == NULL){
195
 
      return NULL;
196
 
    }
197
 
    argv[0] = NULL;     /* Will be set to argv[0] in main before parsing */
198
 
    argv[1] = NULL;
199
 
  }
200
 
  *argc += 1;
201
 
  argv = realloc(argv, sizeof(char *)
202
 
                  * ((unsigned int) *argc + 1));
203
 
  if(argv == NULL){
204
 
    return NULL;
205
 
  }
206
 
  argv[*argc-1] = arg;
207
 
  argv[*argc] = NULL;   
208
 
  return argv;
209
 
}
210
 
 
211
188
int main(int argc, char *argv[]){
212
189
  const char *plugindir = "/conf/conf.d/mandos/plugins.d";
213
 
  const char *conffile = CONFFILE;
214
 
  FILE *conffp;
215
190
  size_t d_name_len;
216
191
  DIR *dir = NULL;
217
192
  struct dirent *dirst;
225
200
  struct sigaction old_sigchld_action;
226
201
  struct sigaction sigchld_action = { .sa_handler = handle_sigchld,
227
202
                                      .sa_flags = SA_NOCLDSTOP };
228
 
  char **custom_argv = NULL;
229
 
  int custom_argc = 0;
230
 
  
 
203
  char *plus_options = NULL;
 
204
  char **plus_argv = NULL;
 
205
 
231
206
  /* Establish a signal handler */
232
207
  sigemptyset(&sigchld_action.sa_mask);
233
208
  ret = sigaddset(&sigchld_action.sa_mask, SIGCHLD);
273
248
    switch (key) {
274
249
    case 'g':
275
250
      if (arg != NULL){
276
 
        char *p;
277
 
        while((p = strsep(&arg, ",")) != NULL){
278
 
          if(p[0] == '\0'){
279
 
            continue;
280
 
          }
 
251
        char *p = strtok(arg, ",");
 
252
        do{
281
253
          addargument(getplugin(NULL, plugins), p);
282
 
        }
 
254
          p = strtok(NULL, ",");
 
255
        } while (p != NULL);
283
256
      }
284
257
      break;
285
258
    case 'o':
286
259
      if (arg != NULL){
287
 
        char *name = strsep(&arg, ":");
288
 
        if(name[0] == '\0'){
289
 
          break;
290
 
        }
291
 
        char *opt = strsep(&arg, ":");
292
 
        if(opt[0] == '\0'){
293
 
          break;
294
 
        }
295
 
        if(opt != NULL){
296
 
          char *p;
297
 
          while((p = strsep(&opt, ",")) != NULL){
298
 
            if(p[0] == '\0'){
299
 
              continue;
300
 
            }
 
260
        char *name = strtok(arg, ":");
 
261
        char *p = strtok(NULL, ":");
 
262
        if(p != NULL){
 
263
          p = strtok(p, ",");
 
264
          do{
301
265
            addargument(getplugin(name, plugins), p);
302
 
          }
 
266
            p = strtok(NULL, ",");
 
267
          } while (p != NULL);
303
268
        }
304
269
      }
305
270
      break;
321
286
      debug = true;
322
287
      break;
323
288
    case ARGP_KEY_ARG:
324
 
      fprintf(stderr, "Ignoring unknown argument \"%s\"\n", arg); 
 
289
      if(plus_options != NULL or arg == NULL or arg[0] != '+'){
 
290
        argp_usage (state);
 
291
      }
 
292
      plus_options = arg;
325
293
      break;
326
294
    case ARGP_KEY_END:
327
295
      break;
343
311
    exitstatus = EXIT_FAILURE;
344
312
    goto end;
345
313
  }
346
 
 
347
 
  conffp = fopen(conffile, "r");
348
 
  if(conffp != NULL){
349
 
    char *org_line = NULL;
350
 
    size_t size = 0;
351
 
    ssize_t sret;
352
 
    char *p, *arg, *new_arg, *line;
353
 
    const char whitespace_delims[] = " \r\t\f\v\n";
354
 
    const char comment_delim[] = "#";
355
 
 
356
 
    while(true){
357
 
      sret = getline(&org_line, &size, conffp);
358
 
      if(sret == -1){
359
 
        break;
360
 
      }
361
 
 
362
 
      line = org_line;
363
 
      arg = strsep(&line, comment_delim);
364
 
      while((p = strsep(&arg, whitespace_delims)) != NULL){
365
 
        if(p[0] == '\0'){
366
 
          continue;
367
 
        }
368
 
        new_arg = strdup(p);
369
 
        custom_argv = addcustomargument(custom_argv, &custom_argc, new_arg);
370
 
        if (custom_argv == NULL){
371
 
          perror("addcustomargument");
372
 
          exitstatus = EXIT_FAILURE;
373
 
          goto end;
374
 
        }
375
 
      }
376
 
    }
377
 
    free(org_line);
378
 
  } else{
379
 
    /* check for harmfull errors */
380
 
    if (errno == EMFILE or errno == ENFILE or errno == ENOMEM){
381
 
      perror("fopen");
 
314
  
 
315
  if(plus_options){
 
316
    /* This is a mangled argument in the form of
 
317
     "+--option+--other-option=parameter+--yet-another-option", etc */
 
318
    /* Make new argc and argv vars, and call argp_parse() again. */
 
319
    plus_options++;             /* skip the first '+' character */
 
320
    const char delims[] = "+";
 
321
    char *arg;
 
322
    int new_argc = 1;
 
323
    plus_argv = malloc(sizeof(char*) * 2);
 
324
    if(plus_argv == NULL){
 
325
      perror("malloc");
382
326
      exitstatus = EXIT_FAILURE;
383
327
      goto end;
384
328
    }
385
 
  }
386
 
 
387
 
  if(custom_argv != NULL){
388
 
    custom_argv[0] = argv[0];
389
 
    ret = argp_parse (&argp, custom_argc, custom_argv, 0, 0, &plugin_list);
 
329
    plus_argv[0] = argv[0];
 
330
    plus_argv[1] = NULL;
 
331
    arg = strtok(plus_options, delims); /* Get first argument */
 
332
    while(arg != NULL){
 
333
      new_argc++;
 
334
      plus_argv = realloc(plus_argv, sizeof(char *)
 
335
                         * ((unsigned int) new_argc + 1));
 
336
      if(plus_argv == NULL){
 
337
        perror("realloc");
 
338
        exitstatus = EXIT_FAILURE;
 
339
        goto end;
 
340
      }
 
341
      plus_argv[new_argc-1] = arg;
 
342
      plus_argv[new_argc] = NULL;
 
343
      arg = strtok(NULL, delims); /* Get next argument */
 
344
    }
 
345
    ret = argp_parse (&argp, new_argc, plus_argv, 0, 0, &plugin_list);
390
346
    if (ret == ARGP_ERR_UNKNOWN){
391
347
      fprintf(stderr, "Unknown error while parsing arguments\n");
392
348
      exitstatus = EXIT_FAILURE;
499
455
    char *filename = malloc(d_name_len + strlen(plugindir) + 2);
500
456
    if (filename == NULL){
501
457
      perror("malloc");
502
 
      continue;
 
458
      exitstatus = EXIT_FAILURE;
 
459
      goto end;
503
460
    }
504
461
    strcpy(filename, plugindir); /* Spurious warning */
505
462
    strcat(filename, "/");      /* Spurious warning */
508
465
    ret = stat(filename, &st);
509
466
    if (ret == -1){
510
467
      perror("stat");
511
 
      free(filename);
512
 
      continue;
 
468
      exitstatus = EXIT_FAILURE;
 
469
      goto end;
513
470
    }
514
471
    
515
472
    if (not S_ISREG(st.st_mode) or (access(filename, X_OK) != 0)){
564
521
    }
565
522
    // Starting a new process to be watched
566
523
    pid_t pid = fork();
567
 
    if(pid == -1){
568
 
      perror("fork");
569
 
      exitstatus = EXIT_FAILURE;
570
 
      goto end;
571
 
    }
572
524
    if(pid == 0){
573
525
      /* this is the child process */
574
526
      ret = sigaction(SIGCHLD, &old_sigchld_action, NULL);
761
713
 end:
762
714
  
763
715
  if(process_list == NULL or exitstatus != EXIT_SUCCESS){
764
 
    /* Fallback if all plugins failed, none are found or an error occured */
 
716
    /* Fallback if all plugins failed or an error occured */
765
717
    bool bret;
766
718
    fprintf(stderr, "Going to fallback mode using getpass(3)\n");
767
719
    char *passwordbuffer = getpass("Password: ");
776
728
  /* Restore old signal handler */
777
729
  sigaction(SIGCHLD, &old_sigchld_action, NULL);
778
730
  
779
 
  free(custom_argv);
 
731
  free(plus_argv);
780
732
  
781
733
  /* Free the plugin list */
782
734
  for(plugin *next; plugin_list != NULL; plugin_list = next){