~d-jj/+junk/sudo

« back to all changes in this revision

Viewing changes to plugins/sudoers/match.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2015-05-13 15:43:49 UTC
  • mfrom: (1.4.17) (1.3.38 sid)
  • Revision ID: package-import@ubuntu.com-20150513154349-3wazxyt6jxlgtgpi
Tags: 1.8.12-1ubuntu1
* Merge from Debian unstable. (LP: #1451274, LP: #1219337)
  Remaining changes:
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets --enable-admin-flag
    + install man/man8/sudo_root.8 in both flavours
    + install apport hooks
  - debian/sudoers:
    + also grant admin group sudo access
  - debian/source_sudo.py, debian/sudo-ldap.dirs, debian/sudo.dirs:
    + add usr/share/apport/package-hooks
  - debian/sudo.pam:
    + Use pam_env to read /etc/environment and /etc/default/locale
      environment files. Reading ~/.pam_environment is not permitted due to
      security reasons.
  - debian/control:
    + dh-autoreconf dependency fixes missing-build-dependency-for-dh_-command
  - Remaining patches:
    + keep_home_by_default.patch: Keep HOME in the default environment
    + debian/patches/also_check_sudo_group.diff: also check the sudo group
      in plugins/sudoers/sudoers.c to create the admin flag file. Leave the
      admin group check for backwards compatibility.
* Dropped patches no longer needed:
    + add_probe_interfaces_setting.diff
    + actually-use-buildflags.diff
    + CVE-2014-9680.patch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (c) 1996, 1998-2005, 2007-2013
 
2
 * Copyright (c) 1996, 1998-2005, 2007-2015
3
3
 *      Todd C. Miller <Todd.Miller@courtesan.com>
4
4
 *
5
5
 * Permission to use, copy, modify, and distribute this software for any
25
25
 
26
26
#include <sys/types.h>
27
27
#include <sys/stat.h>
 
28
#ifdef HAVE_SYS_SYSTEMINFO_H
 
29
# include <sys/systeminfo.h>
 
30
#endif
28
31
#include <stdio.h>
29
32
#ifdef STDC_HEADERS
30
33
# include <stdlib.h>
48
51
#ifdef HAVE_UNISTD_H
49
52
# include <unistd.h>
50
53
#endif /* HAVE_UNISTD_H */
51
 
#ifdef HAVE_FNMATCH
52
 
# include <fnmatch.h>
53
 
#else
54
 
# include "compat/fnmatch.h"
55
 
#endif /* HAVE_FNMATCH */
56
54
#ifndef SUDOERS_NAME_MATCH
57
55
# ifdef HAVE_GLOB
58
56
#  include <glob.h>
81
79
#  include <ndir.h>
82
80
# endif
83
81
#endif
84
 
#include <ctype.h>
85
82
#include <pwd.h>
86
83
#include <grp.h>
87
84
#include <errno.h>
88
85
 
89
86
#include "sudoers.h"
90
87
#include "parse.h"
91
 
#include "sha2.h"
92
88
#include <gram.h>
93
89
 
 
90
#ifdef HAVE_FNMATCH
 
91
# include <fnmatch.h>
 
92
#else
 
93
# include "compat/fnmatch.h"
 
94
#endif /* HAVE_FNMATCH */
 
95
#ifdef HAVE_SHA224UPDATE
 
96
# include <sha2.h>
 
97
#else
 
98
# include "compat/sha2.h"
 
99
#endif
 
100
 
94
101
static struct member_list empty = TAILQ_HEAD_INITIALIZER(empty);
95
102
 
96
103
static bool command_matches_dir(const char *sudoers_dir, size_t dlen);
115
122
    struct member *m;
116
123
    struct alias *a;
117
124
    int rval, matched = UNSPEC;
118
 
    debug_decl(userlist_matches, SUDO_DEBUG_MATCH)
 
125
    debug_decl(userlist_matches, SUDOERS_DEBUG_MATCH)
119
126
 
120
127
    TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
121
128
        switch (m->type) {
165
172
    int rval;
166
173
    int user_matched = UNSPEC;
167
174
    int group_matched = UNSPEC;
168
 
    debug_decl(runaslist_matches, SUDO_DEBUG_MATCH)
 
175
    debug_decl(runaslist_matches, SUDOERS_DEBUG_MATCH)
169
176
 
170
177
    if (runas_pw != NULL) {
171
178
        /* If no runas user or runas group listed in sudoers, use default. */
271
278
    struct member *m;
272
279
    struct alias *a;
273
280
    int rval, matched = UNSPEC;
274
 
    debug_decl(hostlist_matches, SUDO_DEBUG_MATCH)
 
281
    debug_decl(hostlist_matches, SUDOERS_DEBUG_MATCH)
275
282
 
276
283
    TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
277
284
        switch (m->type) {
315
322
{
316
323
    struct member *m;
317
324
    int matched = UNSPEC;
318
 
    debug_decl(cmndlist_matches, SUDO_DEBUG_MATCH)
 
325
    debug_decl(cmndlist_matches, SUDOERS_DEBUG_MATCH)
319
326
 
320
327
    TAILQ_FOREACH_REVERSE(m, list, member_list, entries) {
321
328
        matched = cmnd_matches(m);
335
342
    struct alias *a;
336
343
    struct sudo_command *c;
337
344
    int rval, matched = UNSPEC;
338
 
    debug_decl(cmnd_matches, SUDO_DEBUG_MATCH)
 
345
    debug_decl(cmnd_matches, SUDOERS_DEBUG_MATCH)
339
346
 
340
347
    switch (m->type) {
341
348
        case ALL:
362
369
command_args_match(const char *sudoers_cmnd, const char *sudoers_args)
363
370
{
364
371
    int flags = 0;
365
 
    debug_decl(command_args_match, SUDO_DEBUG_MATCH)
 
372
    debug_decl(command_args_match, SUDOERS_DEBUG_MATCH)
366
373
 
367
374
    /*
368
375
     * If no args specified in sudoers, any user args are allowed.
393
400
command_matches(const char *sudoers_cmnd, const char *sudoers_args, const struct sudo_digest *digest)
394
401
{
395
402
    bool rc = false;
396
 
    debug_decl(command_matches, SUDO_DEBUG_MATCH)
 
403
    debug_decl(command_matches, SUDOERS_DEBUG_MATCH)
397
404
 
398
405
    /* Check for pseudo-commands */
399
406
    if (sudoers_cmnd[0] != '/') {
406
413
        if (strcmp(sudoers_cmnd, "sudoedit") == 0 &&
407
414
            strcmp(user_cmnd, "sudoedit") == 0 &&
408
415
            command_args_match(sudoers_cmnd, sudoers_args)) {
409
 
            efree(safe_cmnd);
410
 
            safe_cmnd = estrdup(sudoers_cmnd);
 
416
            sudo_efree(safe_cmnd);
 
417
            safe_cmnd = sudo_estrdup(sudoers_cmnd);
411
418
            rc = true;
412
419
        }
413
420
        goto done;
441
448
static bool
442
449
command_matches_fnmatch(const char *sudoers_cmnd, const char *sudoers_args)
443
450
{
444
 
    debug_decl(command_matches_fnmatch, SUDO_DEBUG_MATCH)
 
451
    debug_decl(command_matches_fnmatch, SUDOERS_DEBUG_MATCH)
445
452
 
446
453
    /*
447
454
     * Return true if fnmatch(3) succeeds AND
455
462
    if (command_args_match(sudoers_cmnd, sudoers_args)) {
456
463
        if (safe_cmnd)
457
464
            free(safe_cmnd);
458
 
        safe_cmnd = estrdup(user_cmnd);
 
465
        safe_cmnd = sudo_estrdup(user_cmnd);
459
466
        debug_return_bool(true);
460
467
    }
461
468
    debug_return_bool(false);
469
476
    size_t dlen;
470
477
    char **ap, *base, *cp;
471
478
    glob_t gl;
472
 
    debug_decl(command_matches_glob, SUDO_DEBUG_MATCH)
 
479
    debug_decl(command_matches_glob, SUDOERS_DEBUG_MATCH)
473
480
 
474
481
    /*
475
482
     * First check to see if we can avoid the call to glob(3).
516
523
        if (user_stat == NULL ||
517
524
            (user_stat->st_dev == sudoers_stat.st_dev &&
518
525
            user_stat->st_ino == sudoers_stat.st_ino)) {
519
 
            efree(safe_cmnd);
520
 
            safe_cmnd = estrdup(cp);
 
526
            sudo_efree(safe_cmnd);
 
527
            safe_cmnd = sudo_estrdup(cp);
521
528
            break;
522
529
        }
523
530
    }
526
533
        debug_return_bool(false);
527
534
 
528
535
    if (command_args_match(sudoers_cmnd, sudoers_args)) {
529
 
        efree(safe_cmnd);
530
 
        safe_cmnd = estrdup(user_cmnd);
 
536
        sudo_efree(safe_cmnd);
 
537
        safe_cmnd = sudo_estrdup(user_cmnd);
531
538
        debug_return_bool(true);
532
539
    }
533
540
    debug_return_bool(false);
539
546
command_matches_normal(const char *sudoers_cmnd, const char *sudoers_args, const struct sudo_digest *digest)
540
547
{
541
548
    size_t dlen;
542
 
    debug_decl(command_matches_normal, SUDO_DEBUG_MATCH)
 
549
    debug_decl(command_matches_normal, SUDOERS_DEBUG_MATCH)
543
550
 
544
551
    dlen = strlen(sudoers_cmnd);
545
552
 
549
556
 
550
557
    if (strcmp(user_cmnd, sudoers_cmnd) == 0) {
551
558
        if (command_args_match(sudoers_cmnd, sudoers_args)) {
552
 
            efree(safe_cmnd);
553
 
            safe_cmnd = estrdup(sudoers_cmnd);
 
559
            sudo_efree(safe_cmnd);
 
560
            safe_cmnd = sudo_estrdup(sudoers_cmnd);
554
561
            debug_return_bool(true);
555
562
        }
556
563
    }
562
569
    const char *digest_name;
563
570
    const unsigned int digest_len;
564
571
    void (*init)(SHA2_CTX *);
 
572
#ifdef SHA2_VOID_PTR
 
573
    void (*update)(SHA2_CTX *, const void *, size_t);
 
574
    void (*final)(void *, SHA2_CTX *);
 
575
#else
565
576
    void (*update)(SHA2_CTX *, const unsigned char *, size_t);
566
577
    void (*final)(unsigned char *, SHA2_CTX *);
 
578
#endif
567
579
} digest_functions[] = {
568
580
    {
569
581
        "SHA224",
605
617
    SHA2_CTX ctx;
606
618
    FILE *fp;
607
619
    unsigned int i;
608
 
    debug_decl(digest_matches, SUDO_DEBUG_MATCH)
 
620
    int h;
 
621
    debug_decl(digest_matches, SUDOERS_DEBUG_MATCH)
609
622
 
610
623
    for (i = 0; digest_functions[i].digest_name != NULL; i++) {
611
624
        if (sd->digest_type == i) {
614
627
        }
615
628
    }
616
629
    if (func == NULL) {
617
 
        warningx(U_("unsupported digest type %d for %s"), sd->digest_type, file);
 
630
        sudo_warnx(U_("unsupported digest type %d for %s"), sd->digest_type, file);
618
631
        debug_return_bool(false);
619
632
    }
620
633
    if (strlen(sd->digest_str) == func->digest_len * 2) {
621
634
        /* Convert the command digest from ascii hex to binary. */
622
635
        for (i = 0; i < func->digest_len; i++) {
623
 
            if (!isxdigit((unsigned char)sd->digest_str[i + i]) ||
624
 
                !isxdigit((unsigned char)sd->digest_str[i + i + 1])) {
 
636
            h = hexchar(&sd->digest_str[i + i]);
 
637
            if (h == -1)
625
638
                goto bad_format;
626
 
            }
627
 
            sudoers_digest[i] = hexchar(&sd->digest_str[i + i]);
 
639
            sudoers_digest[i] = (unsigned char)h;
628
640
        }
629
641
    } else {
630
642
        size_t len = base64_decode(sd->digest_str, sudoers_digest,
644
656
        func->update(&ctx, buf, nread);
645
657
    }
646
658
    if (ferror(fp)) {
647
 
        warningx(U_("%s: read error"), file);
 
659
        sudo_warnx(U_("%s: read error"), file);
648
660
        fclose(fp);
649
661
        debug_return_bool(false);
650
662
    }
658
670
        func->digest_name, file, sd->digest_str);
659
671
    debug_return_bool(false);
660
672
bad_format:
661
 
    warningx(U_("digest for %s (%s) is not in %s form"), file,
 
673
    sudo_warnx(U_("digest for %s (%s) is not in %s form"), file,
662
674
        sd->digest_str, func->digest_name);
663
675
    debug_return_bool(false);
664
676
}
669
681
    struct stat sudoers_stat;
670
682
    const char *base;
671
683
    size_t dlen;
672
 
    debug_decl(command_matches_normal, SUDO_DEBUG_MATCH)
 
684
    debug_decl(command_matches_normal, SUDOERS_DEBUG_MATCH)
673
685
 
674
686
    /* If it ends in '/' it is a directory spec. */
675
687
    dlen = strlen(sudoers_cmnd);
702
714
        /* XXX - log functions not available but we should log very loudly */
703
715
        debug_return_bool(false);
704
716
    }
705
 
    efree(safe_cmnd);
706
 
    safe_cmnd = estrdup(sudoers_cmnd);
 
717
    sudo_efree(safe_cmnd);
 
718
    safe_cmnd = sudo_estrdup(sudoers_cmnd);
707
719
    debug_return_bool(true);
708
720
}
709
721
#endif /* SUDOERS_NAME_MATCH */
716
728
static bool
717
729
command_matches_dir(const char *sudoers_dir, size_t dlen)
718
730
{
719
 
    debug_decl(command_matches_dir, SUDO_DEBUG_MATCH)
 
731
    debug_decl(command_matches_dir, SUDOERS_DEBUG_MATCH)
720
732
    debug_return_bool(strncmp(user_cmnd, sudoers_dir, dlen) == 0);
721
733
}
722
734
#else /* !SUDOERS_NAME_MATCH */
730
742
    struct dirent *dent;
731
743
    char buf[PATH_MAX];
732
744
    DIR *dirp;
733
 
    debug_decl(command_matches_dir, SUDO_DEBUG_MATCH)
 
745
    debug_decl(command_matches_dir, SUDOERS_DEBUG_MATCH)
734
746
 
735
747
    /*
736
748
     * Grot through directory entries, looking for user_base.
756
768
        if (user_stat == NULL ||
757
769
            (user_stat->st_dev == sudoers_stat.st_dev &&
758
770
            user_stat->st_ino == sudoers_stat.st_ino)) {
759
 
            efree(safe_cmnd);
760
 
            safe_cmnd = estrdup(buf);
 
771
            sudo_efree(safe_cmnd);
 
772
            safe_cmnd = sudo_estrdup(buf);
761
773
            break;
762
774
        }
763
775
    }
773
785
bool
774
786
hostname_matches(const char *shost, const char *lhost, const char *pattern)
775
787
{
776
 
    debug_decl(hostname_matches, SUDO_DEBUG_MATCH)
777
788
    const char *host;
778
789
    bool rc;
 
790
    debug_decl(hostname_matches, SUDOERS_DEBUG_MATCH)
779
791
 
780
792
    host = strchr(pattern, '.') != NULL ? lhost : shost;
781
793
    if (has_meta(pattern)) {
799
811
    const char *errstr;
800
812
    uid_t uid;
801
813
    bool rc;
802
 
    debug_decl(userpw_matches, SUDO_DEBUG_MATCH)
 
814
    debug_decl(userpw_matches, SUDOERS_DEBUG_MATCH)
803
815
 
804
816
    if (pw != NULL && *sudoers_user == '#') {
805
 
        uid = (uid_t) atoid(sudoers_user + 1, NULL, NULL, &errstr);
806
 
        if (errstr != NULL && uid == pw->pw_uid) {
 
817
        uid = (uid_t) sudo_strtoid(sudoers_user + 1, NULL, NULL, &errstr);
 
818
        if (errstr == NULL && uid == pw->pw_uid) {
807
819
            rc = true;
808
820
            goto done;
809
821
        }
826
838
    const char *errstr;
827
839
    gid_t gid;
828
840
    bool rc;
829
 
    debug_decl(group_matches, SUDO_DEBUG_MATCH)
 
841
    debug_decl(group_matches, SUDOERS_DEBUG_MATCH)
830
842
 
831
843
    if (*sudoers_group == '#') {
832
 
        gid = (gid_t) atoid(sudoers_group + 1, NULL, NULL, &errstr);
833
 
        if (errstr != NULL && gid == gr->gr_gid) {
 
844
        gid = (gid_t) sudo_strtoid(sudoers_group + 1, NULL, NULL, &errstr);
 
845
        if (errstr == NULL && gid == gr->gr_gid) {
834
846
            rc = true;
835
847
            goto done;
836
848
        }
852
864
{
853
865
    int matched = false;
854
866
    struct passwd *pw0 = NULL;
855
 
    debug_decl(usergr_matches, SUDO_DEBUG_MATCH)
 
867
    debug_decl(usergr_matches, SUDOERS_DEBUG_MATCH)
856
868
 
857
869
    /* make sure we have a valid usergroup, sudo style */
858
870
    if (*group++ != '%') {
896
908
    debug_return_bool(matched);
897
909
}
898
910
 
899
 
#ifdef HAVE_INNETGR
900
911
/*
901
 
 * Get NIS-style domain name and return a malloc()ed copy or NULL if none.
 
912
 * Get NIS-style domain name and copy from static storage or NULL if none.
902
913
 */
903
 
static char *
 
914
const char *
904
915
sudo_getdomainname(void)
905
916
{
906
917
    char *domain = NULL;
907
 
#ifdef HAVE_GETDOMAINNAME
908
 
    char *buf, *cp;
909
 
 
910
 
    buf = emalloc(HOST_NAME_MAX + 1);
911
 
    if (getdomainname(buf, HOST_NAME_MAX + 1) == 0 && *buf != '\0') {
912
 
        domain = buf;
913
 
        for (cp = buf; *cp != '\0'; cp++) {
914
 
            /* Check for illegal characters, Linux may use "(none)". */
915
 
            if (*cp == '(' || *cp == ')' || *cp == ',' || *cp == ' ') {
916
 
                domain = NULL;
917
 
                break;
 
918
#if defined(HAVE_GETDOMAINNAME) || defined(SI_SRPC_DOMAIN)
 
919
    static char buf[HOST_NAME_MAX + 1];
 
920
    static bool initialized;
 
921
 
 
922
    if (!initialized) {
 
923
        int rval;
 
924
 
 
925
# ifdef SI_SRPC_DOMAIN
 
926
        buf[0] = '\0';
 
927
        rval = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf));
 
928
# else
 
929
        rval = getdomainname(buf, sizeof(buf));
 
930
# endif
 
931
        if (rval != -1 && buf[0] != '\0') {
 
932
            char *cp;
 
933
 
 
934
            domain = buf;
 
935
            for (cp = buf; *cp != '\0'; cp++) {
 
936
                /* Check for illegal characters, Linux may use "(none)". */
 
937
                if (*cp == '(' || *cp == ')' || *cp == ',' || *cp == ' ') {
 
938
                    domain = NULL;
 
939
                    break;
 
940
                }
918
941
            }
919
942
        }
 
943
        initialized = true;
920
944
    }
921
 
    if (domain == NULL)
922
 
        efree(buf);
923
 
#endif /* HAVE_GETDOMAINNAME */
 
945
#endif /* HAVE_GETDOMAINNAME || SI_SRPC_DOMAIN */
924
946
    return domain;
925
947
}
926
 
#endif /* HAVE_INNETGR */
927
948
 
928
949
/*
929
950
 * Returns true if "host" and "user" belong to the netgroup "netgr",
934
955
netgr_matches(const char *netgr, const char *lhost, const char *shost, const char *user)
935
956
{
936
957
#ifdef HAVE_INNETGR
937
 
    static char *domain;
938
 
    static int initialized;
 
958
    const char *domain;
939
959
#endif
940
960
    bool rc = false;
941
 
    debug_decl(netgr_matches, SUDO_DEBUG_MATCH)
 
961
    debug_decl(netgr_matches, SUDOERS_DEBUG_MATCH)
 
962
 
 
963
    if (!def_use_netgroups) {
 
964
        sudo_debug_printf(SUDO_DEBUG_INFO, "netgroups are disabled");
 
965
        debug_return_bool(false);
 
966
    }
942
967
 
943
968
#ifdef HAVE_INNETGR
944
969
    /* make sure we have a valid netgroup, sudo style */
949
974
    }
950
975
 
951
976
    /* get the domain name (if any) */
952
 
    if (!initialized) {
953
 
        domain = sudo_getdomainname();
954
 
        initialized = 1;
955
 
    }
 
977
    domain = sudo_getdomainname();
956
978
 
957
979
    if (innetgr(netgr, lhost, user, domain))
958
980
        rc = true;
959
981
    else if (lhost != shost && innetgr(netgr, shost, user, domain))
960
982
        rc = true;
961
 
#endif /* HAVE_INNETGR */
962
983
 
963
984
    sudo_debug_printf(SUDO_DEBUG_DEBUG|SUDO_DEBUG_LINENO,
964
985
        "netgroup %s matches (%s|%s, %s, %s): %s", netgr, lhost ? lhost : "",
965
986
        shost ? shost : "", user ? user : "", domain ? domain : "",
966
987
        rc ? "true" : "false");
 
988
#endif /* HAVE_INNETGR */
967
989
 
968
990
    debug_return_bool(rc);
969
991
}