1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
|
/* pam_tmpdir module, based on pam_env which in turn was based on
pam_mail */
/*
* $Id: pam_env.c,v 1.3 1999/11/08 05:46:53 morgan Exp $
*
* Written by Tollef Fog Heen <tfheen@err.no> 2001-02-03
*
* Based on pam_env
* Written by Dave Kinchlea <kinch@kinch.ark.com> 1997/01/31
* Inspired by Andrew Morgan <morgan@parc.power.net, who also supplied the
* template for this file (via pam_mail)
*/
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <libgen.h>
#include "util.h"
static int make_tmp_directory() {
int ret;
char *user_tmpdir;
struct stat statbuf;
mode_t old_umask;
char *tmpdir = get_tmp_dir();
if (tmpdir == NULL) {
return 1;
}
/* We want 100% control of permissions */
old_umask = umask(0000);
/* Create $tmpdir */
ret = mkdir(tmpdir,0711);
/* Check whether the mkdir succeeded */
if (ret == -1 && errno != EEXIST) {
_log_err(LOG_NOTICE, "mkdir %s failed: %s\n", tmpdir, strerror(errno));
free(tmpdir);
return 1;
} else if (ret != -1) {
if (chown(tmpdir, 0, 0) == -1) {
_log_err(LOG_NOTICE, "chown 0:0 %s failed: %s\n", tmpdir, strerror(errno));
free(tmpdir);
return 1;
}
}
umask(old_umask);
/* $tmpdir should now exist. Make sure it is
Check that $tmpdir is acceptable */
ret = lstat(tmpdir,&statbuf);
if (ret == -1) {
_log_err(LOG_NOTICE, "%s", "lstat %s failed: %s\n", tmpdir, strerror(errno));
return 1;
} else if (statbuf.st_uid != 0) {
/* Somebody else than root has grabbed /tmp/user. Bad, bad, bad. */
_log_err(LOG_ERR, "%s is owned by uid %d instead of root "
"(uid 0). Failed to create safe $TMPDIR\n", tmpdir,
statbuf.st_uid);
free(tmpdir);
return 1;
} else if (!S_ISDIR(statbuf.st_mode)) {
_log_err(LOG_NOTICE, "%s is not a directory. Failed to create safe "
"$TMPDIR\n", tmpdir);
free(tmpdir);
return 1;
} else if ((statbuf.st_mode & S_IWGRP) || (statbuf.st_mode & S_IWOTH)) {
_log_err(LOG_NOTICE, "%s is group or world writable. "
"Failed to create safe $TMPDIR\n", tmpdir);
free(tmpdir);
return 1;
} else if (!(statbuf.st_mode & S_IXOTH)) {
_log_err(LOG_NOTICE,"%s is not world searchable. "
"Failed to create safe $TMPDIR\n", tmpdir);
free(tmpdir);
return 1;
}
if (asprintf(&user_tmpdir, "%s/%d",tmpdir,getuid()) == -1) {
return 1;
}
/* Create user tmp dir */
ret = mkdir(user_tmpdir,0700);
if (ret == -1 && errno != EEXIST) {
_log_err(LOG_NOTICE, "mkdir %s failed: %s\n", user_tmpdir, strerror(errno));
return 1;
} else if (ret != -1) {
if (chown(user_tmpdir, getuid(), getgid()) == -1) {
_log_err(LOG_NOTICE, "chown %d:%d %s failed: %s\n", getuid(), getgid(),
user_tmpdir, strerror(errno));
return 1;
}
}
ret = lstat(user_tmpdir,&statbuf);
if (ret == -1) {
_log_err(LOG_NOTICE, "lstat %s failed: %s\n", user_tmpdir, strerror(errno));
return 1;
} else if (statbuf.st_uid != getuid()) {
_log_err(LOG_NOTICE, "%s owned by uid %d instead of uid %d. "
"Failed to create safe $TMPDIR\n", user_tmpdir, statbuf.st_uid,
getuid());
return 1;
} else if (!S_ISDIR(statbuf.st_mode)) {
_log_err(LOG_NOTICE, "%s is not a directory. Failed to create safe $TMPDIR\n",
user_tmpdir);
return 1;
}
if ((statbuf.st_mode & S_IWGRP) || (statbuf.st_mode & S_IWOTH)) {
_log_err(LOG_NOTICE, "Warning: %s is group or world writable. "
"Changing permissions to 0700\n", user_tmpdir);
if (chmod(user_tmpdir, 0700) == -1) {
_log_err(LOG_NOTICE, "chmod 0700 %s failed: %s\n", user_tmpdir,
strerror(errno));
return 1;
}
}
return 0;
}
int main(int argc, char **argv) {
(void)argc;
(void)argv;
return make_tmp_directory();
}
|