/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 = NULL;
109
 
  if(name != NULL){
110
 
    copy_name = strdup(name);
111
 
    if(copy_name == NULL){
112
 
      return NULL;
113
 
    }
114
 
  }
115
 
  
116
 
  *new_plugin = (plugin) { .name = copy_name,
 
108
  *new_plugin = (plugin) { .name = name,
117
109
                           .argc = 1,
118
110
                           .envc = 0,
119
111
                           .disabled = false,
121
113
  
122
114
  new_plugin->argv = malloc(sizeof(char *) * 2);
123
115
  if (new_plugin->argv == NULL){
124
 
    free(copy_name);
125
116
    free(new_plugin);
126
117
    return NULL;
127
118
  }
128
 
  new_plugin->argv[0] = copy_name;
 
119
  new_plugin->argv[0] = name;
129
120
  new_plugin->argv[1] = NULL;
130
121
 
131
122
  new_plugin->environ = malloc(sizeof(char *));
132
123
  if(new_plugin->environ == NULL){
133
 
    free(copy_name);
134
124
    free(new_plugin->argv);
135
125
    free(new_plugin);
136
126
    return NULL;
199
189
 
200
190
process *process_list = NULL;
201
191
 
202
 
/* Mark processes as completed when it exits, and save its exit
 
192
/* Mark a process as completed when it exits, and save its exit
203
193
   status. */
204
194
void handle_sigchld(__attribute__((unused)) int sig){
205
195
  process *proc = process_list;
206
 
  while(true){
207
 
    int status;
208
 
    pid_t pid = waitpid(-1, &status, WNOHANG);
209
 
    if(pid == 0){
210
 
      break;
211
 
    }
212
 
    if(pid == -1){
213
 
      if (errno != ECHILD){
214
 
        perror("waitpid");
215
 
      }
216
 
      return;
217
 
    }
218
 
 
219
 
    while(proc != NULL and proc->pid != pid){
220
 
      proc = proc->next;
221
 
    }
222
 
    if(proc == NULL){
223
 
      /* Process not found in process list */
224
 
      continue;
225
 
    }
226
 
    proc->status = status;
227
 
    proc->completed = true;
228
 
  }
 
196
  int status;
 
197
  pid_t pid = wait(&status);
 
198
  if(pid == -1){
 
199
    perror("wait");
 
200
    return;
 
201
  }
 
202
  while(proc != NULL and proc->pid != pid){
 
203
    proc = proc->next;
 
204
  }
 
205
  if(proc == NULL){
 
206
    /* Process not found in process list */
 
207
    return;
 
208
  }
 
209
  proc->status = status;
 
210
  proc->completed = true;
229
211
}
230
212
 
231
213
bool print_out_password(const char *buffer, size_t length){
260
242
    return NULL;
261
243
  }
262
244
  argv[*argc-1] = arg;
263
 
  argv[*argc] = NULL;
 
245
  argv[*argc] = NULL;   
264
246
  return argv;
265
247
}
266
248
 
267
 
static void free_plugin_list(plugin *plugin_list){
268
 
  for(plugin *next; plugin_list != NULL; plugin_list = next){
269
 
    next = plugin_list->next;
270
 
    for(char **arg = plugin_list->argv; *arg != NULL; arg++){
271
 
      free(*arg);
272
 
    }
273
 
    free(plugin_list->argv);
274
 
    for(char **env = plugin_list->environ; *env != NULL; env++){
275
 
      free(*env);
276
 
    }
277
 
    free(plugin_list->environ);
278
 
    free(plugin_list);
279
 
  }
280
 
}
281
 
 
282
249
int main(int argc, char *argv[]){
283
250
  const char *plugindir = "/lib/mandos/plugins.d";
284
251
  const char *argfile = ARGFILE;
302
269
  /* Establish a signal handler */
303
270
  sigemptyset(&sigchld_action.sa_mask);
304
271
  ret = sigaddset(&sigchld_action.sa_mask, SIGCHLD);
305
 
  if(ret == -1){
 
272
  if(ret < 0){
306
273
    perror("sigaddset");
307
 
    exitstatus = EXIT_FAILURE;
308
 
    goto fallback;
 
274
    exit(EXIT_FAILURE);
309
275
  }
310
276
  ret = sigaction(SIGCHLD, &sigchld_action, &old_sigchld_action);
311
 
  if(ret == -1){
 
277
  if(ret < 0){
312
278
    perror("sigaction");
313
 
    exitstatus = EXIT_FAILURE;
314
 
    goto fallback;
 
279
    exit(EXIT_FAILURE);
315
280
  }
316
281
  
317
282
  /* The options we understand. */
463
428
  if (ret == ARGP_ERR_UNKNOWN){
464
429
    fprintf(stderr, "Unknown error while parsing arguments\n");
465
430
    exitstatus = EXIT_FAILURE;
466
 
    goto fallback;
 
431
    goto end;
467
432
  }
468
433
 
469
434
  conffp = fopen(argfile, "r");
470
435
  if(conffp != NULL){
471
436
    char *org_line = NULL;
472
 
    char *p, *arg, *new_arg, *line;
473
437
    size_t size = 0;
474
438
    ssize_t sret;
 
439
    char *p, *arg, *new_arg, *line;
475
440
    const char whitespace_delims[] = " \r\t\f\v\n";
476
441
    const char comment_delim[] = "#";
477
442
 
492
457
        if (custom_argv == NULL){
493
458
          perror("add_to_argv");
494
459
          exitstatus = EXIT_FAILURE;
495
 
          goto fallback;
 
460
          goto end;
496
461
        }
497
462
      }
498
463
    }
503
468
    if (errno == EMFILE or errno == ENFILE or errno == ENOMEM){
504
469
      perror("fopen");
505
470
      exitstatus = EXIT_FAILURE;
506
 
      goto fallback;
 
471
      goto end;
507
472
    }
508
473
  }
509
474
 
513
478
    if (ret == ARGP_ERR_UNKNOWN){
514
479
      fprintf(stderr, "Unknown error while parsing arguments\n");
515
480
      exitstatus = EXIT_FAILURE;
516
 
      goto fallback;
 
481
      goto end;
517
482
    }
518
483
  }
519
484
  
545
510
  if(dir == NULL){
546
511
    perror("Could not open plugin dir");
547
512
    exitstatus = EXIT_FAILURE;
548
 
    goto fallback;
 
513
    goto end;
549
514
  }
550
515
  
551
516
  /* Set the FD_CLOEXEC flag on the directory, if possible */
556
521
      if(ret < 0){
557
522
        perror("set_cloexec_flag");
558
523
        exitstatus = EXIT_FAILURE;
559
 
        goto fallback;
 
524
        goto end;
560
525
      }
561
526
    }
562
527
  }
571
536
      if (errno == EBADF){
572
537
        perror("readdir");
573
538
        exitstatus = EXIT_FAILURE;
574
 
        goto fallback;
 
539
        goto end;
575
540
      }
576
541
      break;
577
542
    }
692
657
      }
693
658
    }
694
659
    
695
 
    int pipefd[2];
 
660
    int pipefd[2]; 
696
661
    ret = pipe(pipefd);
697
662
    if (ret == -1){
698
663
      perror("pipe");
699
664
      exitstatus = EXIT_FAILURE;
700
 
      goto fallback;
 
665
      goto end;
701
666
    }
702
667
    ret = set_cloexec_flag(pipefd[0]);
703
668
    if(ret < 0){
704
669
      perror("set_cloexec_flag");
705
670
      exitstatus = EXIT_FAILURE;
706
 
      goto fallback;
 
671
      goto end;
707
672
    }
708
673
    ret = set_cloexec_flag(pipefd[1]);
709
674
    if(ret < 0){
710
675
      perror("set_cloexec_flag");
711
676
      exitstatus = EXIT_FAILURE;
712
 
      goto fallback;
 
677
      goto end;
713
678
    }
714
679
    /* Block SIGCHLD until process is safely in process list */
715
680
    ret = sigprocmask (SIG_BLOCK, &sigchld_action.sa_mask, NULL);
716
681
    if(ret < 0){
717
682
      perror("sigprocmask");
718
683
      exitstatus = EXIT_FAILURE;
719
 
      goto fallback;
 
684
      goto end;
720
685
    }
721
686
    // Starting a new process to be watched
722
687
    pid_t pid = fork();
723
688
    if(pid == -1){
724
689
      perror("fork");
725
690
      exitstatus = EXIT_FAILURE;
726
 
      goto fallback;
 
691
      goto end;
727
692
    }
728
693
    if(pid == 0){
729
694
      /* this is the child process */
773
738
        perror("sigprocmask");
774
739
      }
775
740
      exitstatus = EXIT_FAILURE;
776
 
      goto fallback;
 
741
      goto end;
777
742
    }
778
743
    
779
744
    *new_process = (struct process){ .pid = pid,
787
752
    if(ret < 0){
788
753
      perror("sigprocmask");
789
754
      exitstatus = EXIT_FAILURE;
790
 
      goto fallback;
 
755
      goto end;
791
756
    }
792
757
    
793
758
    FD_SET(new_process->fd, &rfds_all);
798
763
    
799
764
  }
800
765
  
801
 
  free_plugin_list(plugin_list);
802
 
  plugin_list = NULL;
 
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
  }
803
777
  
804
778
  closedir(dir);
805
779
  dir = NULL;
815
789
    if (select_ret == -1){
816
790
      perror("select");
817
791
      exitstatus = EXIT_FAILURE;
818
 
      goto fallback;
 
792
      goto end;
819
793
    }
820
794
    /* OK, now either a process completed, or something can be read
821
795
       from one of them */
847
821
          if(ret < 0){
848
822
            perror("sigprocmask");
849
823
            exitstatus = EXIT_FAILURE;
850
 
            goto fallback;
 
824
            goto end;
851
825
          }
852
826
          /* Delete this process entry from the list */
853
827
          if(process_list == proc){
882
856
          perror("print_out_password");
883
857
          exitstatus = EXIT_FAILURE;
884
858
        }
885
 
        goto fallback;
 
859
        goto end;
886
860
      }
887
861
      /* This process has not completed.  Does it have any output? */
888
862
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){
896
870
        if (proc->buffer == NULL){
897
871
          perror("malloc");
898
872
          exitstatus = EXIT_FAILURE;
899
 
          goto fallback;
 
873
          goto end;
900
874
        }
901
875
        proc->buffer_size += BUFFER_SIZE;
902
876
      }
917
891
  }
918
892
 
919
893
 
920
 
 fallback:
 
894
 end:
921
895
  
922
896
  if(process_list == NULL or exitstatus != EXIT_SUCCESS){
923
897
    /* Fallback if all plugins failed, none are found or an error occured */
928
902
    if(not bret){
929
903
      perror("print_out_password");
930
904
      exitstatus = EXIT_FAILURE;
 
905
      goto end;
931
906
    }
932
907
  }
933
908
  
934
909
  /* Restore old signal handler */
935
 
  ret = sigaction(SIGCHLD, &old_sigchld_action, NULL);
936
 
  if(ret == -1){
937
 
    perror("sigaction");
938
 
    exitstatus = EXIT_FAILURE;
939
 
  }
940
 
 
941
 
  if(custom_argv != NULL){
942
 
    for(char **arg = custom_argv; *arg != NULL; arg++){
943
 
      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
      }
944
922
    }
945
 
    free(custom_argv);
 
923
    free(plugin_list->environ);
 
924
    free(plugin_list);
946
925
  }
947
 
  free_plugin_list(plugin_list);
948
926
  
949
927
  if(dir != NULL){
950
928
    closedir(dir);