/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 plugins.d/mandos-client.c

  • Committer: Teddy Hogeborn
  • Date: 2016-03-17 20:40:55 UTC
  • mto: (237.7.594 trunk)
  • mto: This revision was merged to the branch mainline in revision 341.
  • Revision ID: teddy@recompile.se-20160317204055-bhsh5xsidq7w5cxu
Client: Fix plymouth agent; broken since 1.7.2.

Fix an very old memory bug in the plymouth agent (which has been
present since its apperance in version 1.2), but which was only
recently detected at run time due to the new -fsanitize=address
compile- time flag, which has been used since version 1.7.2.  This
detection of a memory access violation causes the program to abort,
making the Plymouth graphical boot system unable to accept interactive
input of passwords when using the Mandos client.

* plugins.d/plymouth.c (exec_and_wait): Fix memory allocation bug when
  allocating new_argv.  Also tolerate a zero-length argv.

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 * "browse_callback", and parts of "main".
10
10
 * 
11
11
 * Everything else is
12
 
 * Copyright © 2008-2018 Teddy Hogeborn
13
 
 * Copyright © 2008-2018 Björn Påhlsson
14
 
 * 
15
 
 * This file is part of Mandos.
16
 
 * 
17
 
 * Mandos is free software: you can redistribute it and/or modify it
18
 
 * under the terms of the GNU General Public License as published by
19
 
 * the Free Software Foundation, either version 3 of the License, or
20
 
 * (at your option) any later version.
21
 
 * 
22
 
 * Mandos is distributed in the hope that it will be useful, but
 
12
 * Copyright © 2008-2016 Teddy Hogeborn
 
13
 * Copyright © 2008-2016 Björn Påhlsson
 
14
 * 
 
15
 * This program is free software: you can redistribute it and/or
 
16
 * modify it under the terms of the GNU General Public License as
 
17
 * published by the Free Software Foundation, either version 3 of the
 
18
 * License, or (at your option) any later version.
 
19
 * 
 
20
 * This program is distributed in the hope that it will be useful, but
23
21
 * WITHOUT ANY WARRANTY; without even the implied warranty of
24
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25
23
 * General Public License for more details.
26
24
 * 
27
25
 * You should have received a copy of the GNU General Public License
28
 
 * along with Mandos.  If not, see <http://www.gnu.org/licenses/>.
 
26
 * along with this program.  If not, see
 
27
 * <http://www.gnu.org/licenses/>.
29
28
 * 
30
29
 * Contact the authors at <mandos@recompile.se>.
31
30
 */
48
47
                                   strtof(), abort() */
49
48
#include <stdbool.h>            /* bool, false, true */
50
49
#include <string.h>             /* strcmp(), strlen(), strerror(),
51
 
                                   asprintf(), strncpy(), strsignal()
52
 
                                */
 
50
                                   asprintf(), strncpy() */
53
51
#include <sys/ioctl.h>          /* ioctl */
54
52
#include <sys/types.h>          /* socket(), inet_pton(), sockaddr,
55
53
                                   sockaddr_in6, PF_INET6,
356
354
  /* Create new GPGME "context" */
357
355
  rc = gpgme_new(&(mc->ctx));
358
356
  if(rc != GPG_ERR_NO_ERROR){
359
 
    fprintf_plus(stderr, "bad gpgme_new: %s: %s\n",
360
 
                 gpgme_strsource(rc), gpgme_strerror(rc));
 
357
    fprintf_plus(stderr, "Mandos plugin mandos-client: "
 
358
                 "bad gpgme_new: %s: %s\n", gpgme_strsource(rc),
 
359
                 gpgme_strerror(rc));
361
360
    return false;
362
361
  }
363
362
  
399
398
  /* Create new empty GPGME data buffer for the plaintext */
400
399
  rc = gpgme_data_new(&dh_plain);
401
400
  if(rc != GPG_ERR_NO_ERROR){
402
 
    fprintf_plus(stderr, "bad gpgme_data_new: %s: %s\n",
 
401
    fprintf_plus(stderr, "Mandos plugin mandos-client: "
 
402
                 "bad gpgme_data_new: %s: %s\n",
403
403
                 gpgme_strsource(rc), gpgme_strerror(rc));
404
404
    gpgme_data_release(dh_crypto);
405
405
    return -1;
418
418
      if(result == NULL){
419
419
        fprintf_plus(stderr, "gpgme_op_decrypt_result failed\n");
420
420
      } else {
421
 
        if(result->unsupported_algorithm != NULL) {
422
 
          fprintf_plus(stderr, "Unsupported algorithm: %s\n",
423
 
                       result->unsupported_algorithm);
424
 
        }
425
 
        fprintf_plus(stderr, "Wrong key usage: %s\n",
426
 
                     result->wrong_key_usage ? "Yes" : "No");
 
421
        fprintf_plus(stderr, "Unsupported algorithm: %s\n",
 
422
                     result->unsupported_algorithm);
 
423
        fprintf_plus(stderr, "Wrong key usage: %u\n",
 
424
                     result->wrong_key_usage);
427
425
        if(result->file_name != NULL){
428
426
          fprintf_plus(stderr, "File name: %s\n", result->file_name);
429
427
        }
613
611
        }
614
612
        params.size += (unsigned int)bytes_read;
615
613
      }
616
 
      ret = close(dhpfile);
617
 
      if(ret == -1){
618
 
        perror_plus("close");
619
 
      }
620
614
      if(params.data == NULL){
621
615
        dhparamsfilename = NULL;
622
616
      }
631
625
                     safer_gnutls_strerror(ret));
632
626
        dhparamsfilename = NULL;
633
627
      }
634
 
      free(params.data);
635
628
    } while(false);
636
629
  }
637
630
  if(dhparamsfilename == NULL){
1084
1077
    bool match = false;
1085
1078
    {
1086
1079
      char *interface = NULL;
1087
 
      while((interface = argz_next(mc->interfaces,
1088
 
                                   mc->interfaces_size,
1089
 
                                   interface))){
 
1080
      while((interface=argz_next(mc->interfaces, mc->interfaces_size,
 
1081
                                 interface))){
1090
1082
        if(if_nametoindex(interface) == (unsigned int)if_index){
1091
1083
          match = true;
1092
1084
          break;
1245
1237
           with an explicit route added with the server's address.
1246
1238
           
1247
1239
           Avahi bug reference:
1248
 
           https://lists.freedesktop.org/archives/avahi/2010-February/001833.html
 
1240
           http://lists.freedesktop.org/archives/avahi/2010-February/001833.html
1249
1241
           https://bugs.debian.org/587961
1250
1242
        */
1251
1243
        if(debug){
1431
1423
                                               &decrypted_buffer, mc);
1432
1424
    if(decrypted_buffer_size >= 0){
1433
1425
      
1434
 
      clearerr(stdout);
1435
1426
      written = 0;
1436
1427
      while(written < (size_t) decrypted_buffer_size){
1437
1428
        if(quit_now){
1453
1444
        }
1454
1445
        written += (size_t)ret;
1455
1446
      }
1456
 
      ret = fflush(stdout);
1457
 
      if(ret != 0){
1458
 
        int e = errno;
1459
 
        if(debug){
1460
 
          fprintf_plus(stderr, "Error writing encrypted data: %s\n",
1461
 
                       strerror(errno));
1462
 
        }
1463
 
        errno = e;
1464
 
        goto mandos_end;
1465
 
      }
1466
1447
      retval = 0;
1467
1448
    }
1468
1449
  }
1499
1480
  return retval;
1500
1481
}
1501
1482
 
 
1483
__attribute__((nonnull))
1502
1484
static void resolve_callback(AvahiSServiceResolver *r,
1503
1485
                             AvahiIfIndex interface,
1504
1486
                             AvahiProtocol proto,
1659
1641
      perror_plus("ioctl SIOCGIFFLAGS");
1660
1642
      errno = old_errno;
1661
1643
    }
1662
 
    if((close(s) == -1) and debug){
1663
 
      old_errno = errno;
1664
 
      perror_plus("close");
1665
 
      errno = old_errno;
1666
 
    }
1667
1644
    return false;
1668
1645
  }
1669
 
  if((close(s) == -1) and debug){
1670
 
    old_errno = errno;
1671
 
    perror_plus("close");
1672
 
    errno = old_errno;
1673
 
  }
1674
1646
  return true;
1675
1647
}
1676
1648
 
1937
1909
      return;
1938
1910
    }
1939
1911
  }
1940
 
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
1941
 
  if(devnull == -1){
1942
 
    perror_plus("open(\"/dev/null\", O_RDONLY)");
1943
 
    return;
1944
 
  }
1945
1912
  int numhooks = scandirat(hookdir_fd, ".", &direntries,
1946
1913
                           runnable_hook, alphasort);
1947
1914
  if(numhooks == -1){
1948
1915
    perror_plus("scandir");
1949
 
    close(devnull);
1950
1916
    return;
1951
1917
  }
1952
1918
  struct dirent *direntry;
1953
1919
  int ret;
 
1920
  int devnull = (int)TEMP_FAILURE_RETRY(open("/dev/null", O_RDONLY));
 
1921
  if(devnull == -1){
 
1922
    perror_plus("open(\"/dev/null\", O_RDONLY)");
 
1923
    return;
 
1924
  }
1954
1925
  for(int i = 0; i < numhooks; i++){
1955
1926
    direntry = direntries[i];
1956
1927
    if(debug){
2212
2183
  
2213
2184
  /* Sleep checking until interface is running.
2214
2185
     Check every 0.25s, up to total time of delay */
2215
 
  for(int i = 0; i < delay * 4; i++){
 
2186
  for(int i=0; i < delay * 4; i++){
2216
2187
    if(interface_is_running(interface)){
2217
2188
      break;
2218
2189
    }
2514
2485
  
2515
2486
  {
2516
2487
    /* Work around Debian bug #633582:
2517
 
       <https://bugs.debian.org/633582> */
 
2488
       <http://bugs.debian.org/633582> */
2518
2489
    
2519
2490
    /* Re-raise privileges */
2520
2491
    ret = raise_privileges();
2975
2946
 end:
2976
2947
  
2977
2948
  if(debug){
2978
 
    if(signal_received){
2979
 
      fprintf_plus(stderr, "%s exiting due to signal %d: %s\n",
2980
 
                   argv[0], signal_received,
2981
 
                   strsignal(signal_received));
2982
 
    } else {
2983
 
      fprintf_plus(stderr, "%s exiting\n", argv[0]);
2984
 
    }
 
2949
    fprintf_plus(stderr, "%s exiting\n", argv[0]);
2985
2950
  }
2986
2951
  
2987
2952
  /* Cleanup things */
3039
3004
      /* Take down the network interfaces which were brought up */
3040
3005
      {
3041
3006
        char *interface = NULL;
3042
 
        while((interface = argz_next(interfaces_to_take_down,
3043
 
                                     interfaces_to_take_down_size,
3044
 
                                     interface))){
 
3007
        while((interface=argz_next(interfaces_to_take_down,
 
3008
                                   interfaces_to_take_down_size,
 
3009
                                   interface))){
3045
3010
          ret = take_down_interface(interface);
3046
3011
          if(ret != 0){
3047
3012
            errno = ret;
3076
3041
                                                | O_PATH));
3077
3042
    if(dir_fd == -1){
3078
3043
      perror_plus("open");
3079
 
      return;
3080
3044
    }
3081
3045
    int numentries = scandirat(dir_fd, ".", &direntries,
3082
3046
                               notdotentries, alphasort);
3099
3063
            clean_dir_at(dir_fd, direntries[i]->d_name, level+1);
3100
3064
            dret = 0;
3101
3065
          }
3102
 
          if((dret == -1) and (errno != ENOENT)){
 
3066
          if(dret == -1){
3103
3067
            fprintf_plus(stderr, "unlink(\"%s/%s\"): %s\n", dirname,
3104
3068
                         direntries[i]->d_name, strerror(errno));
3105
3069
          }
3109
3073
      
3110
3074
      /* need to clean even if 0 because man page doesn't specify */
3111
3075
      free(direntries);
 
3076
      if(numentries == -1){
 
3077
        perror_plus("scandirat");
 
3078
      }
3112
3079
      dret = unlinkat(base, dirname, AT_REMOVEDIR);
3113
3080
      if(dret == -1 and errno != ENOENT){
3114
3081
        perror_plus("rmdir");