~ubuntu-branches/ubuntu/raring/sudo/raring

« back to all changes in this revision

Viewing changes to plugins/sudoers/check.c

  • Committer: Package Import Robot
  • Author(s): Tyler Hicks
  • Date: 2012-07-16 14:01:42 UTC
  • mfrom: (1.3.22 sid)
  • Revision ID: package-import@ubuntu.com-20120716140142-b0tgau0k6nid4mrf
Tags: 1.8.5p2-1ubuntu1
* Merge from debian/testing (LP: #1024154), remaining changes:
  - debian/patches/keep_home_by_default.patch:
    + Set HOME in initial_keepenv_table.
  - debian/rules:
    + compile with --without-lecture --with-tty-tickets (Ubuntu specific)
    + install man/man8/sudo_root.8 in both flavours (Ubuntu specific)
    + install apport hooks
    + The ubuntu-sudo-as-admin-successful.patch was taken upstream by
      Debian however it requires a --enable-admin-flag configure flag to
      actually enable it in both flavours.
  - debian/control:
    + Mark Debian Vcs-* as XS-Debian-Vcs-*
    + update debian/control
  - debian/sudoers:
    + 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.
* Dropped changes:
  - debian/patches/lp927828-fix-abort-in-pam-modules-when-timestamp-valid.patch
    + Fixed upstream in 1.8.5
  - debian/patches/CVE-2012-2337.patch:
    + Fixed upstream in 1.8.4p5
  - debian/patches/pam_env_merge.patch:
    + Feature released upstream in 1.8.5
  - debian/{sudo,sudo-ldap}.{preinst,postinst,postrm}:
    + Drop Ubuntu-specific sudoers file migration code because the only
      upgrade path to quantal is from precise. All necessary sudoers file
      migration will have already been done by the time this version of the
      sudo package is installed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
89
89
static char *expand_prompt(char *, char *, char *);
90
90
static void  lecture(int);
91
91
static void  update_timestamp(char *, char *);
92
 
static int   tty_is_devpts(const char *);
 
92
static bool  tty_is_devpts(const char *);
93
93
static struct passwd *get_authpw(void);
94
94
 
95
95
/*
96
 
 * Returns TRUE if the user successfully authenticates, else FALSE.
 
96
 * Returns true if the user successfully authenticates, else false.
97
97
 */
98
98
int
99
99
check_user(int validated, int mode)
103
103
    char *timestampfile = NULL;
104
104
    char *prompt;
105
105
    struct stat sb;
106
 
    int status, rval = TRUE;
107
 
    int need_pass = def_authenticate;
 
106
    int status, rval = true;
 
107
    bool need_pass = def_authenticate;
 
108
    debug_decl(check_user, SUDO_DEBUG_AUTH)
108
109
 
109
110
    /*
110
111
     * Init authentication system regardless of whether we need a password.
128
129
            if (user_uid == 0 || (user_uid == runas_pw->pw_uid &&
129
130
                (!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name)))
130
131
                || user_is_exempt())
131
 
                need_pass = FALSE;
 
132
                need_pass = false;
132
133
        }
133
134
    }
134
135
    if (!need_pass)
169
170
        rval = verify_user(auth_pw, prompt);
170
171
    }
171
172
    /* Only update timestamp if user was validated. */
172
 
    if (rval == TRUE && ISSET(validated, VALIDATE_OK) &&
 
173
    if (rval == true && ISSET(validated, VALIDATE_OK) &&
173
174
        !ISSET(mode, MODE_IGNORE_TICKET) && status != TS_ERROR)
174
175
        update_timestamp(timestampdir, timestampfile);
175
176
    efree(timestampdir);
179
180
    sudo_auth_cleanup(auth_pw);
180
181
    pw_delref(auth_pw);
181
182
 
182
 
    return rval;
 
183
    debug_return_bool(rval);
183
184
}
184
185
 
185
186
#define DEFAULT_LECTURE "\n" \
200
201
    ssize_t nread;
201
202
    struct sudo_conv_message msg;
202
203
    struct sudo_conv_reply repl;
 
204
    debug_decl(lecture, SUDO_DEBUG_AUTH)
203
205
 
204
206
    if (def_lecture == never ||
205
207
        (def_lecture == once && status != TS_MISSING && status != TS_ERROR))
206
 
        return;
 
208
        debug_return;
207
209
 
208
210
    memset(&msg, 0, sizeof(msg));
209
211
    memset(&repl, 0, sizeof(repl));
210
212
 
211
213
    if (def_lecture_file && (fp = fopen(def_lecture_file, "r")) != NULL) {
212
214
        while ((nread = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) != 0) {
213
 
            buf[sizeof(buf) - 1] = '\0';
 
215
            buf[nread] = '\0';
214
216
            msg.msg_type = SUDO_CONV_ERROR_MSG;
215
217
            msg.msg = buf;
216
218
            sudo_conv(1, &msg, &repl);
221
223
        msg.msg = _(DEFAULT_LECTURE);
222
224
        sudo_conv(1, &msg, &repl);
223
225
    }
 
226
    debug_return;
224
227
}
225
228
 
226
229
/*
229
232
static void
230
233
update_timestamp(char *timestampdir, char *timestampfile)
231
234
{
 
235
    debug_decl(update_timestamp, SUDO_DEBUG_AUTH)
 
236
 
232
237
    /* If using tty timestamps but we have no tty there is nothing to do. */
233
238
    if (def_tty_tickets && !user_ttypath)
234
 
        return;
 
239
        debug_return;
235
240
 
236
241
    if (timestamp_uid != 0)
237
242
        set_perms(PERM_TIMESTAMP);
241
246
         */
242
247
        int fd = open(timestampfile, O_WRONLY|O_CREAT, 0600);
243
248
        if (fd == -1)
244
 
            log_error(NO_EXIT|USE_ERRNO, _("unable to open %s"), timestampfile);
 
249
            log_error(USE_ERRNO, _("unable to open %s"), timestampfile);
245
250
        else {
246
251
            lock_file(fd, SUDO_LOCK);
247
252
            if (write(fd, &tty_info, sizeof(tty_info)) != sizeof(tty_info)) {
248
 
                log_error(NO_EXIT|USE_ERRNO, _("unable to write to %s"),
 
253
                log_error(USE_ERRNO, _("unable to write to %s"),
249
254
                    timestampfile);
250
255
            }
251
256
            close(fd);
253
258
    } else {
254
259
        if (touch(-1, timestampdir, NULL) == -1) {
255
260
            if (mkdir(timestampdir, 0700) == -1) {
256
 
                log_error(NO_EXIT|USE_ERRNO, _("unable to mkdir %s"),
 
261
                log_error(USE_ERRNO, _("unable to mkdir %s"),
257
262
                    timestampdir);
258
263
            }
259
264
        }
260
265
    }
261
266
    if (timestamp_uid != 0)
262
267
        restore_perms();
 
268
    debug_return;
263
269
}
264
270
 
265
271
/*
272
278
    size_t len, n;
273
279
    int subst;
274
280
    char *p, *np, *new_prompt, *endp;
 
281
    debug_decl(expand_prompt, SUDO_DEBUG_AUTH)
275
282
 
276
283
    /* How much space do we need to malloc for the prompt? */
277
284
    subst = 0;
382
389
    } else
383
390
        new_prompt = old_prompt;
384
391
 
385
 
    return new_prompt;
 
392
    debug_return_str(new_prompt);
386
393
 
387
394
oflow:
388
395
    /* We pre-allocate enough space, so this should never happen. */
392
399
/*
393
400
 * Checks if the user is exempt from supplying a password.
394
401
 */
395
 
int
 
402
bool
396
403
user_is_exempt(void)
397
404
{
398
 
    if (!def_exempt_group)
399
 
        return FALSE;
400
 
    return user_in_group(sudo_user.pw, def_exempt_group);
 
405
    bool rval = false;
 
406
    debug_decl(user_is_exempt, SUDO_DEBUG_AUTH)
 
407
 
 
408
    if (def_exempt_group)
 
409
        rval = user_in_group(sudo_user.pw, def_exempt_group);
 
410
    debug_return_bool(rval);
401
411
}
402
412
 
403
413
/*
408
418
{
409
419
    char *dirparent;
410
420
    int len;
 
421
    debug_decl(build_timestamp, SUDO_DEBUG_AUTH)
411
422
 
412
423
    dirparent = def_timestampdir;
413
424
    len = easprintf(timestampdir, "%s/%s", dirparent, user_name);
440
451
    } else
441
452
        *timestampfile = NULL;
442
453
 
443
 
    return len;
 
454
    debug_return_int(len);
444
455
bad:
445
 
    log_error(0, _("timestamp path too long: %s"), *timestampfile);
446
 
    return -1;
 
456
    log_fatal(0, _("timestamp path too long: %s"), *timestampfile);
 
457
    debug_return_int(-1);
447
458
}
448
459
 
449
460
/*
457
468
    time_t now;
458
469
    char *dirparent = def_timestampdir;
459
470
    int status = TS_ERROR;              /* assume the worst */
 
471
    debug_decl(timestamp_status, SUDO_DEBUG_AUTH)
460
472
 
461
473
    if (timestamp_uid != 0)
462
474
        set_perms(PERM_TIMESTAMP);
470
482
     */
471
483
    if (lstat(dirparent, &sb) == 0) {
472
484
        if (!S_ISDIR(sb.st_mode))
473
 
            log_error(NO_EXIT, _("%s exists but is not a directory (0%o)"),
 
485
            log_error(0, _("%s exists but is not a directory (0%o)"),
474
486
                dirparent, (unsigned int) sb.st_mode);
475
487
        else if (sb.st_uid != timestamp_uid)
476
 
            log_error(NO_EXIT, _("%s owned by uid %u, should be uid %u"),
 
488
            log_error(0, _("%s owned by uid %u, should be uid %u"),
477
489
                dirparent, (unsigned int) sb.st_uid,
478
490
                (unsigned int) timestamp_uid);
479
491
        else if ((sb.st_mode & 0000022))
480
 
            log_error(NO_EXIT,
 
492
            log_error(0,
481
493
                _("%s writable by non-owner (0%o), should be mode 0700"),
482
494
                dirparent, (unsigned int) sb.st_mode);
483
495
        else {
486
498
            status = TS_MISSING;
487
499
        }
488
500
    } else if (errno != ENOENT) {
489
 
        log_error(NO_EXIT|USE_ERRNO, _("unable to stat %s"), dirparent);
 
501
        log_error(USE_ERRNO, _("unable to stat %s"), dirparent);
490
502
    } else {
491
503
        /* No dirparent, try to make one. */
492
504
        if (ISSET(flags, TS_MAKE_DIRS)) {
493
505
            if (mkdir(dirparent, S_IRWXU))
494
 
                log_error(NO_EXIT|USE_ERRNO, _("unable to mkdir %s"),
 
506
                log_error(USE_ERRNO, _("unable to mkdir %s"),
495
507
                    dirparent);
496
508
            else
497
509
                status = TS_MISSING;
514
526
                if (unlink(timestampdir) == 0)
515
527
                    status = TS_MISSING;
516
528
            } else
517
 
                log_error(NO_EXIT, _("%s exists but is not a directory (0%o)"),
 
529
                log_error(0, _("%s exists but is not a directory (0%o)"),
518
530
                    timestampdir, (unsigned int) sb.st_mode);
519
531
        } else if (sb.st_uid != timestamp_uid)
520
 
            log_error(NO_EXIT, _("%s owned by uid %u, should be uid %u"),
 
532
            log_error(0, _("%s owned by uid %u, should be uid %u"),
521
533
                timestampdir, (unsigned int) sb.st_uid,
522
534
                (unsigned int) timestamp_uid);
523
535
        else if ((sb.st_mode & 0000022))
524
 
            log_error(NO_EXIT,
 
536
            log_error(0,
525
537
                _("%s writable by non-owner (0%o), should be mode 0700"),
526
538
                timestampdir, (unsigned int) sb.st_mode);
527
539
        else {
530
542
            status = TS_OLD;            /* do date check later */
531
543
        }
532
544
    } else if (errno != ENOENT) {
533
 
        log_error(NO_EXIT|USE_ERRNO, _("unable to stat %s"), timestampdir);
 
545
        log_error(USE_ERRNO, _("unable to stat %s"), timestampdir);
534
546
    } else
535
547
        status = TS_MISSING;
536
548
 
541
553
    if (status == TS_MISSING && timestampfile && ISSET(flags, TS_MAKE_DIRS)) {
542
554
        if (mkdir(timestampdir, S_IRWXU) == -1) {
543
555
            status = TS_ERROR;
544
 
            log_error(NO_EXIT|USE_ERRNO, _("unable to mkdir %s"), timestampdir);
 
556
            log_error(USE_ERRNO, _("unable to mkdir %s"), timestampdir);
545
557
        }
546
558
    }
547
559
 
556
568
        if (lstat(timestampfile, &sb) == 0) {
557
569
            if (!S_ISREG(sb.st_mode)) {
558
570
                status = TS_ERROR;
559
 
                log_error(NO_EXIT, _("%s exists but is not a regular file (0%o)"),
 
571
                log_error(0, _("%s exists but is not a regular file (0%o)"),
560
572
                    timestampfile, (unsigned int) sb.st_mode);
561
573
            } else {
562
574
                /* If bad uid or file mode, complain and kill the bogus file. */
563
575
                if (sb.st_uid != timestamp_uid) {
564
 
                    log_error(NO_EXIT,
 
576
                    log_error(0,
565
577
                        _("%s owned by uid %u, should be uid %u"),
566
578
                        timestampfile, (unsigned int) sb.st_uid,
567
579
                        (unsigned int) timestamp_uid);
568
580
                    (void) unlink(timestampfile);
569
581
                } else if ((sb.st_mode & 0000022)) {
570
 
                    log_error(NO_EXIT,
 
582
                    log_error(0,
571
583
                        _("%s writable by non-owner (0%o), should be mode 0600"),
572
584
                        timestampfile, (unsigned int) sb.st_mode);
573
585
                    (void) unlink(timestampfile);
598
610
                }
599
611
            }
600
612
        } else if (errno != ENOENT) {
601
 
            log_error(NO_EXIT|USE_ERRNO, _("unable to stat %s"), timestampfile);
 
613
            log_error(USE_ERRNO, _("unable to stat %s"), timestampfile);
602
614
            status = TS_ERROR;
603
615
        }
604
616
    }
621
633
                 */
622
634
                if (mtime.tv_sec > now + 60 * def_timestamp_timeout * 2) {
623
635
                    time_t tv_sec = (time_t)mtime.tv_sec;
624
 
                    log_error(NO_EXIT,
 
636
                    log_error(0,
625
637
                        _("timestamp too far in the future: %20.20s"),
626
638
                        4 + ctime(&tv_sec));
627
639
                    if (timestampfile)
641
653
done:
642
654
    if (timestamp_uid != 0)
643
655
        restore_perms();
644
 
    return status;
 
656
    debug_return_int(status);
645
657
}
646
658
 
647
659
/*
648
660
 * Remove the timestamp ticket file/dir.
649
661
 */
650
662
void
651
 
remove_timestamp(int remove)
 
663
remove_timestamp(bool remove)
652
664
{
653
665
    struct timeval tv;
654
666
    char *timestampdir, *timestampfile, *path;
655
667
    int status;
 
668
    debug_decl(remove_timestamp, SUDO_DEBUG_AUTH)
656
669
 
657
670
    if (build_timestamp(&timestampdir, &timestampfile) == -1)
658
 
        return;
 
671
        debug_return;
659
672
 
660
673
    status = timestamp_status(timestampdir, timestampfile, user_name,
661
674
        TS_REMOVE);
667
680
            else
668
681
                status = rmdir(timestampdir);
669
682
            if (status == -1 && errno != ENOENT) {
670
 
                log_error(NO_EXIT,
 
683
                log_error(0,
671
684
                    _("unable to remove %s (%s), will reset to the epoch"),
672
685
                    path, strerror(errno));
673
 
                remove = FALSE;
 
686
                remove = false;
674
687
            }
675
688
        }
676
689
        if (!remove) {
679
692
                error(1, _("unable to reset %s to the epoch"), path);
680
693
        }
681
694
    }
682
 
 
683
695
    efree(timestampdir);
684
696
    efree(timestampfile);
 
697
 
 
698
    debug_return;
685
699
}
686
700
 
687
701
/*
688
 
 * Returns TRUE if tty lives on a devpts or /devices filesystem, else FALSE.
689
 
 * Unlike most filesystems, the ctime of devpts nodes is not updated when
690
 
 * the device node is written to, only when the inode's status changes,
 
702
 * Returns true if tty lives on a devpts, /dev or /devices filesystem, else
 
703
 * false.  Unlike most filesystems, the ctime of devpts nodes is not updated
 
704
 * when the device node is written to, only when the inode's status changes,
691
705
 * typically via the chmod, chown, link, rename, or utimes system calls.
692
706
 * Since the ctime is "stable" in this case, we can stash it the tty ticket
693
707
 * file and use it to determine whether the tty ticket file is stale.
694
708
 */
695
 
static int
 
709
static bool
696
710
tty_is_devpts(const char *tty)
697
711
{
698
 
    int retval = FALSE;
 
712
    bool retval = false;
699
713
#ifdef __linux__
700
714
    struct statfs sfs;
 
715
    debug_decl(tty_is_devpts, SUDO_DEBUG_PTY)
701
716
 
702
717
#ifndef DEVPTS_SUPER_MAGIC
703
718
# define DEVPTS_SUPER_MAGIC 0x1cd1
705
720
 
706
721
    if (statfs(tty, &sfs) == 0) {
707
722
        if (sfs.f_type == DEVPTS_SUPER_MAGIC)
708
 
            retval = TRUE;
 
723
            retval = true;
709
724
    }
710
725
#elif defined(__sun) && defined(__SVR4)
711
726
    struct statvfs sfs;
 
727
    debug_decl(tty_is_devpts, SUDO_DEBUG_PTY)
712
728
 
713
729
    if (statvfs(tty, &sfs) == 0) {
714
 
        if (strcmp(sfs.f_fstr, "devices") == 0)
715
 
            retval = TRUE;
 
730
        if (strcmp(sfs.f_fstr, "dev") == 0 || strcmp(sfs.f_fstr, "devices") == 0)
 
731
            retval = true;
716
732
    }
 
733
#else
 
734
    debug_decl(tty_is_devpts, SUDO_DEBUG_PTY)
717
735
#endif /* __linux__ */
718
 
    return retval;
 
736
    debug_return_bool(retval);
719
737
}
720
738
 
721
739
/*
727
745
get_authpw(void)
728
746
{
729
747
    struct passwd *pw;
 
748
    debug_decl(get_authpw, SUDO_DEBUG_AUTH)
730
749
 
731
750
    if (def_rootpw) {
732
751
        if ((pw = sudo_getpwuid(ROOT_UID)) == NULL)
733
 
            log_error(0, _("unknown uid: %u"), ROOT_UID);
 
752
            log_fatal(0, _("unknown uid: %u"), ROOT_UID);
734
753
    } else if (def_runaspw) {
735
754
        if ((pw = sudo_getpwnam(def_runas_default)) == NULL)
736
 
            log_error(0, _("unknown user: %s"), def_runas_default);
 
755
            log_fatal(0, _("unknown user: %s"), def_runas_default);
737
756
    } else if (def_targetpw) {
738
757
        if (runas_pw->pw_name == NULL)
739
 
            log_error(NO_MAIL|MSG_ONLY, _("unknown uid: %u"),
 
758
            log_fatal(NO_MAIL|MSG_ONLY, _("unknown uid: %u"),
740
759
                (unsigned int) runas_pw->pw_uid);
741
760
        pw_addref(runas_pw);
742
761
        pw = runas_pw;
745
764
        pw = sudo_user.pw;
746
765
    }
747
766
 
748
 
    return pw;
 
767
    debug_return_ptr(pw);
749
768
}