mirror of
https://github.com/Yubico/yubico-pam.git
synced 2025-02-21 15:54:41 +01:00
Drop privileges before opening user files.
This change also ensures that user tokens are regular files. We may want to add a similar check for user challenge files.
This commit is contained in:
parent
f92ee12aa9
commit
a9892dbb44
104
drop_privs.c
Normal file
104
drop_privs.c
Normal file
@ -0,0 +1,104 @@
|
||||
/* Written by Ricky Zhou <ricky@fedoraproject.org>
|
||||
* Copyright (c) 2011 Ricky Zhou <ricky@fedoraproject.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following
|
||||
* disclaimer in the documentation and/or other materials provided
|
||||
* with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
#include <grp.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
static uid_t saved_euid;
|
||||
static gid_t saved_egid;
|
||||
|
||||
static gid_t *saved_groups;
|
||||
static int saved_groups_length;
|
||||
|
||||
int drop_privileges(struct passwd *pw) {
|
||||
saved_euid = geteuid();
|
||||
saved_egid = getegid();
|
||||
|
||||
saved_groups_length = getgroups(0, NULL);
|
||||
if (saved_groups_length < 0) {
|
||||
D (("getgroups: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (saved_groups_length > 0) {
|
||||
saved_groups = malloc(saved_groups_length * sizeof(gid_t));
|
||||
if (saved_groups == NULL) {
|
||||
D (("malloc: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (getgroups(saved_groups_length, saved_groups) < 0) {
|
||||
D (("getgroups: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
|
||||
D (("initgroups: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setegid(pw->pw_gid) < 0) {
|
||||
D (("setegid: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (seteuid(pw->pw_uid) < 0) {
|
||||
D (("seteuid: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int restore_privileges(void) {
|
||||
if (seteuid(saved_euid) < 0) {
|
||||
D (("seteuid: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setegid(saved_egid) < 0) {
|
||||
D (("setegid: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setgroups(saved_groups_length, saved_groups) < 0) {
|
||||
D (("setgroups: %s", strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(saved_groups);
|
||||
|
||||
return 0;
|
||||
}
|
9
drop_privs.h
Normal file
9
drop_privs.h
Normal file
@ -0,0 +1,9 @@
|
||||
#ifndef __PAM_YUBICO_DROP_PRIVS_H_INCLUDED__
|
||||
#define __PAM_YUBICO_DROP_PRIVS_H_INCLUDED__
|
||||
|
||||
#include <pwd.h>
|
||||
|
||||
int drop_privileges(struct passwd *);
|
||||
int restore_privileges(void);
|
||||
|
||||
#endif
|
76
pam_yubico.c
76
pam_yubico.c
@ -34,7 +34,14 @@
|
||||
#include <ctype.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "drop_privs.h"
|
||||
|
||||
/* Libtool defines PIC for shared objects */
|
||||
#ifndef PIC
|
||||
@ -125,14 +132,34 @@ check_user_token (struct cfg *cfg,
|
||||
char buf[1024];
|
||||
char *s_user, *s_token;
|
||||
int retval = 0;
|
||||
int fd;
|
||||
struct stat st;
|
||||
FILE *opwfile;
|
||||
|
||||
opwfile = fopen (authfile, "r");
|
||||
if (opwfile == NULL)
|
||||
{
|
||||
fd = open(authfile, O_RDONLY, 0);
|
||||
if (fd < 0) {
|
||||
DBG (("Cannot open file: %s", authfile));
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) < 0) {
|
||||
DBG (("Cannot stat file: %s", authfile));
|
||||
close(fd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
DBG (("%s is not a regular file", authfile));
|
||||
close(fd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
opwfile = fdopen(fd, "r");
|
||||
if (opwfile == NULL) {
|
||||
DBG (("fdopen: %s", strerror(errno)));
|
||||
close(fd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
while (fgets (buf, 1024, opwfile))
|
||||
{
|
||||
@ -173,6 +200,18 @@ authorize_user_token (struct cfg *cfg,
|
||||
const char *otp_id)
|
||||
{
|
||||
int retval;
|
||||
struct passwd *p;
|
||||
|
||||
p = getpwnam (username);
|
||||
if (p == NULL) {
|
||||
DBG (("getpwnam: %s", strerror(errno)));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (drop_privileges(p) < 0) {
|
||||
D (("could not drop privileges"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cfg->auth_file)
|
||||
{
|
||||
@ -196,6 +235,12 @@ authorize_user_token (struct cfg *cfg,
|
||||
free (userfile);
|
||||
}
|
||||
|
||||
if (restore_privileges() < 0)
|
||||
{
|
||||
DBG (("could not restore privileges"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
@ -356,6 +401,7 @@ authorize_user_token_ldap (struct cfg *cfg,
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if HAVE_LIBYKPERS_1
|
||||
static int
|
||||
display_error(pam_handle_t *pamh, char *message) {
|
||||
struct pam_conv *conv;
|
||||
@ -383,6 +429,7 @@ display_error(pam_handle_t *pamh, char *message) {
|
||||
D(("conv returned: '%s'", resp->resp));
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBYKPERS_1
|
||||
static int
|
||||
@ -402,6 +449,8 @@ do_challenge_response(pam_handle_t *pamh, struct cfg *cfg, const char *username)
|
||||
int len;
|
||||
char *errstr = NULL;
|
||||
|
||||
struct passwd *p;
|
||||
|
||||
ret = PAM_AUTH_ERR;
|
||||
flags |= YK_FLAG_MAYBLOCK;
|
||||
|
||||
@ -423,7 +472,19 @@ do_challenge_response(pam_handle_t *pamh, struct cfg *cfg, const char *username)
|
||||
|
||||
DBG(("Loading challenge from file %s", userfile));
|
||||
|
||||
/* XXX should drop root privileges before opening file in user's home directory */
|
||||
p = getpwnam (username);
|
||||
if (p == NULL) {
|
||||
DBG (("getpwnam: %s", strerror(errno)));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Drop privileges before opening user file. */
|
||||
if (drop_privileges(p) < 0) {
|
||||
D (("could not drop privileges"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* XXX may want to check that userfile is a regular file. */
|
||||
f = fopen(userfile, "r");
|
||||
|
||||
if (! load_chalresp_state(f, &state))
|
||||
@ -434,6 +495,11 @@ do_challenge_response(pam_handle_t *pamh, struct cfg *cfg, const char *username)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (restore_privileges() < 0) {
|
||||
DBG (("could not restore privileges"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (! challenge_response(yk, state.slot, state.challenge, state.challenge_len,
|
||||
true, flags, false,
|
||||
buf, sizeof(buf), &response_len)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user