/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

  • Committer: Teddy Hogeborn
  • Date: 2011-12-31 20:07:11 UTC
  • mfrom: (535.1.9 wireless-network-hook)
  • Revision ID: teddy@recompile.se-20111231200711-6dli3r8drftem57r
Merge new wireless network hook.  Fix bridge network hook to use
hardware addresses instead of interface names.  Implement and document
new "CONNECT" environment variable for network hooks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Mandos plugin runner - Run Mandos plugins
4
4
 *
5
 
 * Copyright © 2008-2013 Teddy Hogeborn
6
 
 * Copyright © 2008-2013 Björn Påhlsson
 
5
 * Copyright © 2008-2011 Teddy Hogeborn
 
6
 * Copyright © 2008-2011 Björn Påhlsson
7
7
 * 
8
8
 * This program is free software: you can redistribute it and/or
9
9
 * modify it under the terms of the GNU General Public License as
105
105
 
106
106
/* Gets an existing plugin based on name,
107
107
   or if none is found, creates a new one */
108
 
__attribute__((warn_unused_result))
109
108
static plugin *getplugin(char *name){
110
109
  /* Check for existing plugin with that name */
111
110
  for(plugin *p = plugin_list; p != NULL; p = p->next){
172
171
}
173
172
 
174
173
/* Helper function for add_argument and add_environment */
175
 
__attribute__((nonnull, warn_unused_result))
 
174
__attribute__((nonnull))
176
175
static bool add_to_char_array(const char *new, char ***array,
177
176
                              int *len){
178
177
  /* Resize the pointed-to array to hold one more pointer */
179
 
  char **new_array = NULL;
180
178
  do {
181
 
    new_array = realloc(*array, sizeof(char *)
182
 
                        * (size_t) ((*len) + 2));
183
 
  } while(new_array == NULL and errno == EINTR);
 
179
    *array = realloc(*array, sizeof(char *)
 
180
                     * (size_t) ((*len) + 2));
 
181
  } while(*array == NULL and errno == EINTR);
184
182
  /* Malloc check */
185
 
  if(new_array == NULL){
 
183
  if(*array == NULL){
186
184
    return false;
187
185
  }
188
 
  *array = new_array;
189
186
  /* Make a copy of the new string */
190
187
  char *copy;
191
188
  do {
203
200
}
204
201
 
205
202
/* Add to a plugin's argument vector */
206
 
__attribute__((nonnull(2), warn_unused_result))
 
203
__attribute__((nonnull(2)))
207
204
static bool add_argument(plugin *p, const char *arg){
208
205
  if(p == NULL){
209
206
    return false;
212
209
}
213
210
 
214
211
/* Add to a plugin's environment */
215
 
__attribute__((nonnull(2), warn_unused_result))
 
212
__attribute__((nonnull(2)))
216
213
static bool add_environment(plugin *p, const char *def, bool replace){
217
214
  if(p == NULL){
218
215
    return false;
220
217
  /* namelen = length of name of environment variable */
221
218
  size_t namelen = (size_t)(strchrnul(def, '=') - def);
222
219
  /* Search for this environment variable */
223
 
  for(char **envdef = p->environ; *envdef != NULL; envdef++){
224
 
    if(strncmp(*envdef, def, namelen + 1) == 0){
 
220
  for(char **e = p->environ; *e != NULL; e++){
 
221
    if(strncmp(*e, def, namelen + 1) == 0){
225
222
      /* It already exists */
226
223
      if(replace){
227
 
        char *new_envdef;
 
224
        char *new;
228
225
        do {
229
 
          new_envdef = realloc(*envdef, strlen(def) + 1);
230
 
        } while(new_envdef == NULL and errno == EINTR);
231
 
        if(new_envdef == NULL){
 
226
          new = realloc(*e, strlen(def) + 1);
 
227
        } while(new == NULL and errno == EINTR);
 
228
        if(new == NULL){
232
229
          return false;
233
230
        }
234
 
        *envdef = new_envdef;
235
 
        strcpy(*envdef, def);
 
231
        *e = new;
 
232
        strcpy(*e, def);
236
233
      }
237
234
      return true;
238
235
    }
245
242
 * Descriptor Flags".
246
243
 | [[info:libc:Descriptor%20Flags][File Descriptor Flags]] |
247
244
 */
248
 
__attribute__((warn_unused_result))
249
245
static int set_cloexec_flag(int fd){
250
246
  int ret = (int)TEMP_FAILURE_RETRY(fcntl(fd, F_GETFD, 0));
251
247
  /* If reading the flags failed, return error indication now. */
293
289
}
294
290
 
295
291
/* Prints out a password to stdout */
296
 
__attribute__((nonnull, warn_unused_result))
 
292
__attribute__((nonnull))
297
293
static bool print_out_password(const char *buffer, size_t length){
298
294
  ssize_t ret;
299
295
  for(size_t written = 0; written < length; written += (size_t)ret){
439
435
            break;
440
436
          }
441
437
        }
442
 
        errno = 0;
443
438
      }
444
439
      break;
445
440
    case 'G':                   /* --global-env */
446
 
      if(add_environment(getplugin(NULL), arg, true)){
447
 
        errno = 0;
448
 
      }
 
441
      add_environment(getplugin(NULL), arg, true);
449
442
      break;
450
443
    case 'o':                   /* --options-for */
451
444
      {
468
461
            break;
469
462
          }
470
463
        }
471
 
        errno = 0;
472
464
      }
473
465
      break;
474
466
    case 'E':                   /* --env-for */
486
478
          errno = EINVAL;
487
479
          break;
488
480
        }
489
 
        if(add_environment(getplugin(arg), envdef, true)){
490
 
          errno = 0;
491
 
        }
 
481
        add_environment(getplugin(arg), envdef, true);
492
482
      }
493
483
      break;
494
484
    case 'd':                   /* --disable */
496
486
        plugin *p = getplugin(arg);
497
487
        if(p != NULL){
498
488
          p->disabled = true;
499
 
          errno = 0;
500
489
        }
501
490
      }
502
491
      break;
505
494
        plugin *p = getplugin(arg);
506
495
        if(p != NULL){
507
496
          p->disabled = false;
508
 
          errno = 0;
509
497
        }
510
498
      }
511
499
      break;
512
500
    case 128:                   /* --plugin-dir */
513
501
      free(plugindir);
514
502
      plugindir = strdup(arg);
515
 
      if(plugindir != NULL){
516
 
        errno = 0;
517
 
      }
518
503
      break;
519
504
    case 129:                   /* --config-file */
520
505
      /* This is already done by parse_opt_config_file() */
528
513
        break;
529
514
      }
530
515
      uid = (uid_t)tmp_id;
531
 
      errno = 0;
532
516
      break;
533
517
    case 131:                   /* --groupid */
534
518
      tmp_id = strtoimax(arg, &tmp, 10);
539
523
        break;
540
524
      }
541
525
      gid = (gid_t)tmp_id;
542
 
      errno = 0;
543
526
      break;
544
527
    case 132:                   /* --debug */
545
528
      debug = true;
593
576
    case 129:                   /* --config-file */
594
577
      free(argfile);
595
578
      argfile = strdup(arg);
596
 
      if(argfile != NULL){
597
 
        errno = 0;
598
 
      }
599
579
      break;
600
580
    case 130:                   /* --userid */
601
581
    case 131:                   /* --groupid */
684
664
        }
685
665
        
686
666
        custom_argc += 1;
687
 
        {
688
 
          char **new_argv = realloc(custom_argv, sizeof(char *)
689
 
                                    * ((unsigned int)
690
 
                                       custom_argc + 1));
691
 
          if(new_argv == NULL){
692
 
            error(0, errno, "realloc");
693
 
            exitstatus = EX_OSERR;
694
 
            free(new_arg);
695
 
            free(org_line);
696
 
            goto fallback;
697
 
          } else {
698
 
            custom_argv = new_argv;
699
 
          }
 
667
        custom_argv = realloc(custom_argv, sizeof(char *)
 
668
                              * ((unsigned int) custom_argc + 1));
 
669
        if(custom_argv == NULL){
 
670
          error(0, errno, "realloc");
 
671
          exitstatus = EX_OSERR;
 
672
          free(org_line);
 
673
          goto fallback;
700
674
        }
701
675
        custom_argv[custom_argc-1] = new_arg;
702
676
        custom_argv[custom_argc] = NULL;
797
771
  }
798
772
  
799
773
  /* Lower permissions */
800
 
  ret = setgid(gid);
 
774
  setgid(gid);
801
775
  if(ret == -1){
802
776
    error(0, errno, "setgid");
803
777
  }
876
850
    {
877
851
      bool bad_name = false;
878
852
      
879
 
      const char * const bad_prefixes[] = { ".", "#", NULL };
 
853
      const char const *bad_prefixes[] = { ".", "#", NULL };
880
854
      
881
 
      const char * const bad_suffixes[] = { "~", "#", ".dpkg-new",
 
855
      const char const *bad_suffixes[] = { "~", "#", ".dpkg-new",
882
856
                                           ".dpkg-old",
883
857
                                           ".dpkg-bak",
884
858
                                           ".dpkg-divert", NULL };
885
 
#ifdef __GNUC__
886
 
#pragma GCC diagnostic push
887
 
#pragma GCC diagnostic ignored "-Wcast-qual"
888
 
#endif
889
 
      for(const char **pre = (const char **)bad_prefixes;
890
 
          *pre != NULL; pre++){
891
 
#ifdef __GNUC__
892
 
#pragma GCC diagnostic pop
893
 
#endif
 
859
      for(const char **pre = bad_prefixes; *pre != NULL; pre++){
894
860
        size_t pre_len = strlen(*pre);
895
861
        if((d_name_len >= pre_len)
896
862
           and strncmp((dirst->d_name), *pre, pre_len) == 0){
905
871
      if(bad_name){
906
872
        continue;
907
873
      }
908
 
#ifdef __GNUC__
909
 
#pragma GCC diagnostic push
910
 
#pragma GCC diagnostic ignored "-Wcast-qual"
911
 
#endif
912
 
      for(const char **suf = (const char **)bad_suffixes;
913
 
          *suf != NULL; suf++){
914
 
#ifdef __GNUC__
915
 
#pragma GCC diagnostic pop
916
 
#endif
 
874
      for(const char **suf = bad_suffixes; *suf != NULL; suf++){
917
875
        size_t suf_len = strlen(*suf);
918
876
        if((d_name_len >= suf_len)
919
877
           and (strcmp((dirst->d_name) + d_name_len-suf_len, *suf)
1113
1071
      goto fallback;
1114
1072
    }
1115
1073
    
1116
 
#if defined (__GNUC__) and defined (__GLIBC__)
1117
 
#if not __GLIBC_PREREQ(2, 16)
1118
 
#pragma GCC diagnostic push
1119
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1120
 
#endif
1121
 
#endif
1122
1074
    FD_SET(new_plugin->fd, &rfds_all); /* Spurious warning from
1123
 
                                          -Wconversion in GNU libc
1124
 
                                          before 2.16 */
1125
 
#if defined (__GNUC__) and defined (__GLIBC__)
1126
 
#if not __GLIBC_PREREQ(2, 16)
1127
 
#pragma GCC diagnostic pop
1128
 
#endif
1129
 
#endif
 
1075
                                          -Wconversion */
1130
1076
    
1131
1077
    if(maxfd < new_plugin->fd){
1132
1078
      maxfd = new_plugin->fd;
1186
1132
          }
1187
1133
          
1188
1134
          /* Remove the plugin */
1189
 
#if defined (__GNUC__) and defined (__GLIBC__)
1190
 
#if not __GLIBC_PREREQ(2, 16)
1191
 
#pragma GCC diagnostic push
1192
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1193
 
#endif
1194
 
#endif
1195
1135
          FD_CLR(proc->fd, &rfds_all); /* Spurious warning from
1196
 
                                          -Wconversion in GNU libc
1197
 
                                          before 2.16 */
1198
 
#if defined (__GNUC__) and defined (__GLIBC__)
1199
 
#if not __GLIBC_PREREQ(2, 16)
1200
 
#pragma GCC diagnostic pop
1201
 
#endif
1202
 
#endif
 
1136
                                          -Wconversion */
1203
1137
          
1204
1138
          /* Block signal while modifying process_list */
1205
1139
          ret = (int)TEMP_FAILURE_RETRY(sigprocmask
1245
1179
      }
1246
1180
      
1247
1181
      /* This process has not completed.  Does it have any output? */
1248
 
#if defined (__GNUC__) and defined (__GLIBC__)
1249
 
#if not __GLIBC_PREREQ(2, 16)
1250
 
#pragma GCC diagnostic push
1251
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1252
 
#endif
1253
 
#endif
1254
1182
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){ /* Spurious
1255
1183
                                                         warning from
1256
 
                                                         -Wconversion
1257
 
                                                         in GNU libc
1258
 
                                                         before
1259
 
                                                         2.16 */
1260
 
#if defined (__GNUC__) and defined (__GLIBC__)
1261
 
#if not __GLIBC_PREREQ(2, 16)
1262
 
#pragma GCC diagnostic pop
1263
 
#endif
1264
 
#endif
 
1184
                                                         -Wconversion */
1265
1185
        /* This process had nothing to say at this time */
1266
1186
        proc = proc->next;
1267
1187
        continue;
1268
1188
      }
1269
1189
      /* Before reading, make the process' data buffer large enough */
1270
1190
      if(proc->buffer_length + BUFFER_SIZE > proc->buffer_size){
1271
 
        char *new_buffer = realloc(proc->buffer, proc->buffer_size
1272
 
                                   + (size_t) BUFFER_SIZE);
1273
 
        if(new_buffer == NULL){
 
1191
        proc->buffer = realloc(proc->buffer, proc->buffer_size
 
1192
                               + (size_t) BUFFER_SIZE);
 
1193
        if(proc->buffer == NULL){
1274
1194
          error(0, errno, "malloc");
1275
1195
          exitstatus = EX_OSERR;
1276
1196
          goto fallback;
1277
1197
        }
1278
 
        proc->buffer = new_buffer;
1279
1198
        proc->buffer_size += BUFFER_SIZE;
1280
1199
      }
1281
1200
      /* Read from the process */