/mandos/release

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

« back to all changes in this revision

Viewing changes to plugin-runner.c

* Makefile (BROKEN_PIE): Add comment.
* debian/rules (BROKEN_PIE): - '' -
* plugin-runner.c: Really always use <sysexits.h> exit codes.
* plugins.d/mandos-client.c: Use <sysexits.h> exit codes.
  (start_mandos_communication): Make sure errno is always set when
                                returning -1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#define _GNU_SOURCE             /* TEMP_FAILURE_RETRY(), getline(),
26
26
                                   asprintf(), O_CLOEXEC */
27
27
#include <stddef.h>             /* size_t, NULL */
28
 
#include <stdlib.h>             /* malloc(), exit(), EXIT_FAILURE,
29
 
                                   EXIT_SUCCESS, realloc() */
 
28
#include <stdlib.h>             /* malloc(), exit(), EXIT_SUCCESS,
 
29
                                   realloc() */
30
30
#include <stdbool.h>            /* bool, true, false */
31
31
#include <stdio.h>              /* perror, fileno(), fprintf(),
32
32
                                   stderr, STDOUT_FILENO */
68
68
                                */
69
69
#include <errno.h>              /* errno, EBADF */
70
70
#include <inttypes.h>           /* intmax_t, PRIdMAX, strtoimax() */
71
 
#include <sysexits.h>           /* EX_OSERR, EX_USAGE */
 
71
#include <sysexits.h>           /* EX_OSERR, EX_USAGE, EX_IOERR,
 
72
                                   EX_CONFIG, EX_UNAVAILABLE, EX_OK */
72
73
 
73
74
#define BUFFER_SIZE 256
74
75
 
357
358
  ret = sigaddset(&sigchld_action.sa_mask, SIGCHLD);
358
359
  if(ret == -1){
359
360
    perror("sigaddset");
360
 
    exitstatus = EXIT_FAILURE;
 
361
    exitstatus = EX_OSERR;
361
362
    goto fallback;
362
363
  }
363
364
  ret = sigaction(SIGCHLD, &sigchld_action, &old_sigchld_action);
364
365
  if(ret == -1){
365
366
    perror("sigaction");
366
 
    exitstatus = EXIT_FAILURE;
 
367
    exitstatus = EX_OSERR;
367
368
    goto fallback;
368
369
  }
369
370
  
626
627
    custom_argv = malloc(sizeof(char*) * 2);
627
628
    if(custom_argv == NULL){
628
629
      perror("malloc");
629
 
      exitstatus = EXIT_FAILURE;
 
630
      exitstatus = EX_OSERR;
630
631
      goto fallback;
631
632
    }
632
633
    custom_argv[0] = argv[0];
649
650
        new_arg = strdup(p);
650
651
        if(new_arg == NULL){
651
652
          perror("strdup");
652
 
          exitstatus = EXIT_FAILURE;
 
653
          exitstatus = EX_OSERR;
653
654
          free(org_line);
654
655
          goto fallback;
655
656
        }
659
660
                              * ((unsigned int) custom_argc + 1));
660
661
        if(custom_argv == NULL){
661
662
          perror("realloc");
662
 
          exitstatus = EXIT_FAILURE;
 
663
          exitstatus = EX_OSERR;
663
664
          free(org_line);
664
665
          goto fallback;
665
666
        }
672
673
    } while(ret == EOF and errno == EINTR);
673
674
    if(ret == EOF){
674
675
      perror("fclose");
675
 
      exitstatus = EXIT_FAILURE;
 
676
      exitstatus = EX_IOERR;
676
677
      goto fallback;
677
678
    }
678
679
    free(org_line);
681
682
       not affect opening plugins */
682
683
    if(errno == EMFILE or errno == ENFILE or errno == ENOMEM){
683
684
      perror("fopen");
684
 
      exitstatus = EXIT_FAILURE;
 
685
      exitstatus = EX_IOERR;
685
686
      goto fallback;
686
687
    }
687
688
  }
771
772
    }
772
773
    if(dir_fd == -1){
773
774
      perror("Could not open plugin dir");
774
 
      exitstatus = EXIT_FAILURE;
 
775
      exitstatus = EX_UNAVAILABLE;
775
776
      goto fallback;
776
777
    }
777
778
    
781
782
    if(ret < 0){
782
783
      perror("set_cloexec_flag");
783
784
      TEMP_FAILURE_RETRY(close(dir_fd));
784
 
      exitstatus = EXIT_FAILURE;
 
785
      exitstatus = EX_OSERR;
785
786
      goto fallback;
786
787
    }
787
788
#endif  /* O_CLOEXEC */
790
791
    if(dir == NULL){
791
792
      perror("Could not open plugin dir");
792
793
      TEMP_FAILURE_RETRY(close(dir_fd));
793
 
      exitstatus = EXIT_FAILURE;
 
794
      exitstatus = EX_OSERR;
794
795
      goto fallback;
795
796
    }
796
797
  }
807
808
    if(dirst == NULL){
808
809
      if(errno == EBADF){
809
810
        perror("readdir");
810
 
        exitstatus = EXIT_FAILURE;
 
811
        exitstatus = EX_IOERR;
811
812
        goto fallback;
812
813
      }
813
814
      break;
937
938
    ret = (int)TEMP_FAILURE_RETRY(pipe(pipefd));
938
939
    if(ret == -1){
939
940
      perror("pipe");
940
 
      exitstatus = EXIT_FAILURE;
 
941
      exitstatus = EX_OSERR;
941
942
      goto fallback;
942
943
    }
943
944
    /* Ask OS to automatic close the pipe on exec */
944
945
    ret = set_cloexec_flag(pipefd[0]);
945
946
    if(ret < 0){
946
947
      perror("set_cloexec_flag");
947
 
      exitstatus = EXIT_FAILURE;
 
948
      exitstatus = EX_OSERR;
948
949
      goto fallback;
949
950
    }
950
951
    ret = set_cloexec_flag(pipefd[1]);
951
952
    if(ret < 0){
952
953
      perror("set_cloexec_flag");
953
 
      exitstatus = EXIT_FAILURE;
 
954
      exitstatus = EX_OSERR;
954
955
      goto fallback;
955
956
    }
956
957
    /* Block SIGCHLD until process is safely in process list */
959
960
                                              NULL));
960
961
    if(ret < 0){
961
962
      perror("sigprocmask");
962
 
      exitstatus = EXIT_FAILURE;
 
963
      exitstatus = EX_OSERR;
963
964
      goto fallback;
964
965
    }
965
966
    /* Starting a new process to be watched */
969
970
    } while(pid == -1 and errno == EINTR);
970
971
    if(pid == -1){
971
972
      perror("fork");
972
 
      exitstatus = EXIT_FAILURE;
 
973
      exitstatus = EX_OSERR;
973
974
      goto fallback;
974
975
    }
975
976
    if(pid == 0){
977
978
      ret = sigaction(SIGCHLD, &old_sigchld_action, NULL);
978
979
      if(ret < 0){
979
980
        perror("sigaction");
980
 
        _exit(EXIT_FAILURE);
 
981
        _exit(EX_OSERR);
981
982
      }
982
983
      ret = sigprocmask(SIG_UNBLOCK, &sigchld_action.sa_mask, NULL);
983
984
      if(ret < 0){
984
985
        perror("sigprocmask");
985
 
        _exit(EXIT_FAILURE);
 
986
        _exit(EX_OSERR);
986
987
      }
987
988
      
988
989
      ret = dup2(pipefd[1], STDOUT_FILENO); /* replace our stdout */
989
990
      if(ret == -1){
990
991
        perror("dup2");
991
 
        _exit(EXIT_FAILURE);
 
992
        _exit(EX_OSERR);
992
993
      }
993
994
      
994
995
      if(dirfd(dir) < 0){
999
1000
      if(p->environ[0] == NULL){
1000
1001
        if(execv(filename, p->argv) < 0){
1001
1002
          perror("execv");
1002
 
          _exit(EXIT_FAILURE);
 
1003
          _exit(EX_OSERR);
1003
1004
        }
1004
1005
      } else {
1005
1006
        if(execve(filename, p->argv, p->environ) < 0){
1006
1007
          perror("execve");
1007
 
          _exit(EXIT_FAILURE);
 
1008
          _exit(EX_OSERR);
1008
1009
        }
1009
1010
      }
1010
1011
      /* no return */
1022
1023
      if(ret < 0){
1023
1024
        perror("sigprocmask");
1024
1025
      }
1025
 
      exitstatus = EXIT_FAILURE;
 
1026
      exitstatus = EX_OSERR;
1026
1027
      goto fallback;
1027
1028
    }
1028
1029
    
1036
1037
                                              NULL));
1037
1038
    if(ret < 0){
1038
1039
      perror("sigprocmask");
1039
 
      exitstatus = EXIT_FAILURE;
 
1040
      exitstatus = EX_OSERR;
1040
1041
      goto fallback;
1041
1042
    }
1042
1043
    
1069
1070
    int select_ret = select(maxfd+1, &rfds, NULL, NULL, NULL);
1070
1071
    if(select_ret == -1 and errno != EINTR){
1071
1072
      perror("select");
1072
 
      exitstatus = EXIT_FAILURE;
 
1073
      exitstatus = EX_OSERR;
1073
1074
      goto fallback;
1074
1075
    }
1075
1076
    /* OK, now either a process completed, or something can be read
1111
1112
                                         NULL));
1112
1113
          if(ret < 0){
1113
1114
            perror("sigprocmask");
1114
 
            exitstatus = EXIT_FAILURE;
 
1115
            exitstatus = EX_OSERR;
1115
1116
            goto fallback;
1116
1117
          }
1117
1118
          
1125
1126
                                   &sigchld_action.sa_mask, NULL)));
1126
1127
          if(ret < 0){
1127
1128
            perror("sigprocmask");
1128
 
            exitstatus = EXIT_FAILURE;
 
1129
            exitstatus = EX_OSERR;
1129
1130
            goto fallback;
1130
1131
          }
1131
1132
          
1142
1143
                                       proc->buffer_length);
1143
1144
        if(not bret){
1144
1145
          perror("print_out_password");
1145
 
          exitstatus = EXIT_FAILURE;
 
1146
          exitstatus = EX_IOERR;
1146
1147
        }
1147
1148
        goto fallback;
1148
1149
      }
1161
1162
                               + (size_t) BUFFER_SIZE);
1162
1163
        if(proc->buffer == NULL){
1163
1164
          perror("malloc");
1164
 
          exitstatus = EXIT_FAILURE;
 
1165
          exitstatus = EX_OSERR;
1165
1166
          goto fallback;
1166
1167
        }
1167
1168
        proc->buffer_size += BUFFER_SIZE;
1188
1189
  
1189
1190
 fallback:
1190
1191
  
1191
 
  if(plugin_list == NULL or exitstatus != EXIT_SUCCESS){
 
1192
  if(plugin_list == NULL or (exitstatus != EXIT_SUCCESS
 
1193
                             and exitstatus != EX_OK)){
1192
1194
    /* Fallback if all plugins failed, none are found or an error
1193
1195
       occured */
1194
1196
    bool bret;
1203
1205
    bret = print_out_password(passwordbuffer, len);
1204
1206
    if(not bret){
1205
1207
      perror("print_out_password");
1206
 
      exitstatus = EXIT_FAILURE;
 
1208
      exitstatus = EX_IOERR;
1207
1209
    }
1208
1210
  }
1209
1211
  
1211
1213
  ret = sigaction(SIGCHLD, &old_sigchld_action, NULL);
1212
1214
  if(ret == -1){
1213
1215
    perror("sigaction");
1214
 
    exitstatus = EXIT_FAILURE;
 
1216
    exitstatus = EX_OSERR;
1215
1217
  }
1216
1218
  
1217
1219
  if(custom_argv != NULL){