/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 plugin-runner.c

merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
105
105
  if (new_plugin == NULL){
106
106
    return NULL;
107
107
  }
108
 
  char *copy_name = strdup(name);
109
 
  if(copy_name == NULL){
110
 
    return NULL;
111
 
  }
112
 
  
113
 
  *new_plugin = (plugin) { .name = copy_name,
 
108
  *new_plugin = (plugin) { .name = name,
114
109
                           .argc = 1,
115
110
                           .envc = 0,
116
111
                           .disabled = false,
121
116
    free(new_plugin);
122
117
    return NULL;
123
118
  }
124
 
  new_plugin->argv[0] = copy_name;
 
119
  new_plugin->argv[0] = name;
125
120
  new_plugin->argv[1] = NULL;
126
121
 
127
122
  new_plugin->environ = malloc(sizeof(char *));
251
246
  return argv;
252
247
}
253
248
 
254
 
static void free_plugin_list(plugin *plugin_list){
255
 
  for(plugin *next = plugin_list; plugin_list != NULL; plugin_list = next){
256
 
    next = plugin_list->next;
257
 
    free(plugin_list->name);
258
 
    for(char **arg = plugin_list->argv; *arg != NULL; arg++){
259
 
      free(*arg);
260
 
    }    
261
 
    free(plugin_list->argv);
262
 
    for(char **env = plugin_list->environ; *env != NULL; env++){
263
 
      free(*env);
264
 
    }
265
 
    free(plugin_list->environ);
266
 
    free(plugin_list);
267
 
  }  
268
 
}
269
 
 
270
249
int main(int argc, char *argv[]){
271
250
  const char *plugindir = "/lib/mandos/plugins.d";
272
251
  const char *argfile = ARGFILE;
290
269
  /* Establish a signal handler */
291
270
  sigemptyset(&sigchld_action.sa_mask);
292
271
  ret = sigaddset(&sigchld_action.sa_mask, SIGCHLD);
293
 
  if(ret == -1){
 
272
  if(ret < 0){
294
273
    perror("sigaddset");
295
 
    exitstatus = EXIT_FAILURE;
296
 
    goto fallback;
 
274
    exit(EXIT_FAILURE);
297
275
  }
298
276
  ret = sigaction(SIGCHLD, &sigchld_action, &old_sigchld_action);
299
 
  if(ret == -1){
 
277
  if(ret < 0){
300
278
    perror("sigaction");
301
 
    exitstatus = EXIT_FAILURE;    
302
 
    goto fallback;
 
279
    exit(EXIT_FAILURE);
303
280
  }
304
281
  
305
282
  /* The options we understand. */
451
428
  if (ret == ARGP_ERR_UNKNOWN){
452
429
    fprintf(stderr, "Unknown error while parsing arguments\n");
453
430
    exitstatus = EXIT_FAILURE;
454
 
    goto fallback;
 
431
    goto end;
455
432
  }
456
433
 
457
434
  conffp = fopen(argfile, "r");
458
435
  if(conffp != NULL){
459
436
    char *org_line = NULL;
460
 
    char *p, *arg, *new_arg, *line;
461
437
    size_t size = 0;
462
438
    ssize_t sret;
 
439
    char *p, *arg, *new_arg, *line;
463
440
    const char whitespace_delims[] = " \r\t\f\v\n";
464
441
    const char comment_delim[] = "#";
465
442
 
480
457
        if (custom_argv == NULL){
481
458
          perror("add_to_argv");
482
459
          exitstatus = EXIT_FAILURE;
483
 
          goto fallback;
 
460
          goto end;
484
461
        }
485
462
      }
486
463
    }
491
468
    if (errno == EMFILE or errno == ENFILE or errno == ENOMEM){
492
469
      perror("fopen");
493
470
      exitstatus = EXIT_FAILURE;
494
 
      goto fallback;
 
471
      goto end;
495
472
    }
496
473
  }
497
474
 
501
478
    if (ret == ARGP_ERR_UNKNOWN){
502
479
      fprintf(stderr, "Unknown error while parsing arguments\n");
503
480
      exitstatus = EXIT_FAILURE;
504
 
      goto fallback;
 
481
      goto end;
505
482
    }
506
483
  }
507
484
  
533
510
  if(dir == NULL){
534
511
    perror("Could not open plugin dir");
535
512
    exitstatus = EXIT_FAILURE;
536
 
    goto fallback;
 
513
    goto end;
537
514
  }
538
515
  
539
516
  /* Set the FD_CLOEXEC flag on the directory, if possible */
544
521
      if(ret < 0){
545
522
        perror("set_cloexec_flag");
546
523
        exitstatus = EXIT_FAILURE;
547
 
        goto fallback;
 
524
        goto end;
548
525
      }
549
526
    }
550
527
  }
559
536
      if (errno == EBADF){
560
537
        perror("readdir");
561
538
        exitstatus = EXIT_FAILURE;
562
 
        goto fallback;
 
539
        goto end;
563
540
      }
564
541
      break;
565
542
    }
685
662
    if (ret == -1){
686
663
      perror("pipe");
687
664
      exitstatus = EXIT_FAILURE;
688
 
      goto fallback;
 
665
      goto end;
689
666
    }
690
667
    ret = set_cloexec_flag(pipefd[0]);
691
668
    if(ret < 0){
692
669
      perror("set_cloexec_flag");
693
670
      exitstatus = EXIT_FAILURE;
694
 
      goto fallback;
 
671
      goto end;
695
672
    }
696
673
    ret = set_cloexec_flag(pipefd[1]);
697
674
    if(ret < 0){
698
675
      perror("set_cloexec_flag");
699
676
      exitstatus = EXIT_FAILURE;
700
 
      goto fallback;
 
677
      goto end;
701
678
    }
702
679
    /* Block SIGCHLD until process is safely in process list */
703
680
    ret = sigprocmask (SIG_BLOCK, &sigchld_action.sa_mask, NULL);
704
681
    if(ret < 0){
705
682
      perror("sigprocmask");
706
683
      exitstatus = EXIT_FAILURE;
707
 
      goto fallback;
 
684
      goto end;
708
685
    }
709
686
    // Starting a new process to be watched
710
687
    pid_t pid = fork();
711
688
    if(pid == -1){
712
689
      perror("fork");
713
690
      exitstatus = EXIT_FAILURE;
714
 
      goto fallback;
 
691
      goto end;
715
692
    }
716
693
    if(pid == 0){
717
694
      /* this is the child process */
761
738
        perror("sigprocmask");
762
739
      }
763
740
      exitstatus = EXIT_FAILURE;
764
 
      goto fallback;
 
741
      goto end;
765
742
    }
766
743
    
767
744
    *new_process = (struct process){ .pid = pid,
775
752
    if(ret < 0){
776
753
      perror("sigprocmask");
777
754
      exitstatus = EXIT_FAILURE;
778
 
      goto fallback;
 
755
      goto end;
779
756
    }
780
757
    
781
758
    FD_SET(new_process->fd, &rfds_all);
786
763
    
787
764
  }
788
765
  
789
 
  free_plugin_list(plugin_list);
 
766
  /* Free the plugin list */
 
767
  for(plugin *next; plugin_list != NULL; plugin_list = next){
 
768
    next = plugin_list->next;
 
769
    free(plugin_list->argv);
 
770
    if(plugin_list->environ[0] != NULL){
 
771
      for(char **e = plugin_list->environ; *e != NULL; e++){
 
772
        free(*e);
 
773
      }
 
774
    }
 
775
    free(plugin_list);
 
776
  }
790
777
  
791
778
  closedir(dir);
792
779
  dir = NULL;
802
789
    if (select_ret == -1){
803
790
      perror("select");
804
791
      exitstatus = EXIT_FAILURE;
805
 
      goto fallback;
 
792
      goto end;
806
793
    }
807
794
    /* OK, now either a process completed, or something can be read
808
795
       from one of them */
834
821
          if(ret < 0){
835
822
            perror("sigprocmask");
836
823
            exitstatus = EXIT_FAILURE;
837
 
            goto fallback;
 
824
            goto end;
838
825
          }
839
826
          /* Delete this process entry from the list */
840
827
          if(process_list == proc){
869
856
          perror("print_out_password");
870
857
          exitstatus = EXIT_FAILURE;
871
858
        }
872
 
        goto fallback;
 
859
        goto end;
873
860
      }
874
861
      /* This process has not completed.  Does it have any output? */
875
862
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){
883
870
        if (proc->buffer == NULL){
884
871
          perror("malloc");
885
872
          exitstatus = EXIT_FAILURE;
886
 
          goto fallback;
 
873
          goto end;
887
874
        }
888
875
        proc->buffer_size += BUFFER_SIZE;
889
876
      }
904
891
  }
905
892
 
906
893
 
907
 
 fallback:
 
894
 end:
908
895
  
909
896
  if(process_list == NULL or exitstatus != EXIT_SUCCESS){
910
897
    /* Fallback if all plugins failed, none are found or an error occured */
915
902
    if(not bret){
916
903
      perror("print_out_password");
917
904
      exitstatus = EXIT_FAILURE;
 
905
      goto end;
918
906
    }
919
907
  }
920
908
  
921
909
  /* Restore old signal handler */
922
 
  ret = sigaction(SIGCHLD, &old_sigchld_action, NULL);
923
 
  if(ret == -1){
924
 
    perror("sigaction");
925
 
    exitstatus = EXIT_FAILURE;
926
 
  }
927
 
 
928
 
  if(custom_argv != NULL){
929
 
    for(char **arg = custom_argv; *arg != NULL; arg++){
930
 
      free(*arg);
 
910
  sigaction(SIGCHLD, &old_sigchld_action, NULL);
 
911
  
 
912
  free(custom_argv);
 
913
  
 
914
  /* Free the plugin list */
 
915
  for(plugin *next; plugin_list != NULL; plugin_list = next){
 
916
    next = plugin_list->next;
 
917
    free(plugin_list->argv);
 
918
    if(plugin_list->environ[0] != NULL){
 
919
      for(char **e = plugin_list->environ; *e != NULL; e++){
 
920
        free(*e);
 
921
      }
931
922
    }
932
 
    free(custom_argv);
 
923
    free(plugin_list->environ);
 
924
    free(plugin_list);
933
925
  }
934
 
  free_plugin_list(plugin_list);
935
926
  
936
927
  if(dir != NULL){
937
928
    closedir(dir);