"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/mount_davfs.c" between
davfs2-1.6.1.tar.gz and davfs2-1.7.0.tar.gz

About: davfs2 is a file system driver that allows you to mount a WebDAV server as a disk drive.

mount_davfs.c  (davfs2-1.6.1):mount_davfs.c  (davfs2-1.7.0)
skipping to change at line 23 skipping to change at line 23
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with davfs2; if not, write to the Free Software Foundation, along with davfs2; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
#include "config.h" #include "config.h"
#include <ctype.h> #include <ctype.h>
#include <errno.h>
#include <error.h>
#ifdef HAVE_FCNTL_H #ifdef HAVE_FCNTL_H
#include <fcntl.h> #include <fcntl.h>
#endif #endif
#include <getopt.h> #include <getopt.h>
#include <grp.h> #include <grp.h>
#ifdef HAVE_LIBINTL_H #ifdef HAVE_LIBINTL_H
#include <libintl.h> #include <libintl.h>
#endif #endif
#ifdef HAVE_LIMITS_H #ifdef HAVE_LIMITS_H
#include <limits.h> #include <limits.h>
skipping to change at line 75 skipping to change at line 73
#ifdef HAVE_SYS_MOUNT_H #ifdef HAVE_SYS_MOUNT_H
#include <sys/mount.h> #include <sys/mount.h>
#endif #endif
#ifdef HAVE_SYS_STAT_H #ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#ifdef HAVE_SYS_TYPES_H #ifdef HAVE_SYS_TYPES_H
#include <sys/types.h> #include <sys/types.h>
#endif #endif
#ifndef __linux__
#include <sys/sysctl.h>
#endif
#include <fstab.h>
#include <ne_string.h> #include <ne_string.h>
#include <ne_uri.h> #include <ne_uri.h>
#include <ne_utils.h> #include <ne_utils.h>
#include "util.h"
#include "defaults.h" #include "defaults.h"
#include "mount_davfs.h" #include "mount_davfs.h"
#include "kernel_interface.h" #include "kernel_interface.h"
#include "cache.h" #include "cache.h"
#include "webdav.h" #include "webdav.h"
#ifdef ENABLE_NLS #ifdef ENABLE_NLS
#define _(String) gettext(String) #define _(String) gettext(String)
#else #else
#define _(String) String #define _(String) String
#define textdomain(Domainname) #define textdomain(Domainname)
#define bindtextdomain(Domainname, Dirname) #define bindtextdomain(Domainname, Dirname)
#endif #endif
#ifdef __FreeBSD__
#define VFS_USERMOUNT "vfs.usermount"
#endif
/* Private global variables */ /* Private global variables */
/*==========================*/ /*==========================*/
/* The URL of the WebDAV server as taken from commandline. */ /* The URL of the WebDAV server as taken from commandline. */
static char *url; static char *url;
/* The canonicalized mointpoint. */ /* The canonicalized mointpoint. */
static char *mpoint; static char *mpoint;
#ifdef __linux__
/* The file that holds information about mounted filesystems /* The file that holds information about mounted filesystems
(/proc/mounts or /etc/mtab) */ (/proc/mounts or /etc/mtab) */
static char *mounts; static char *mounts;
#endif
/* The PID file */ /* The PID file */
static char *pidfile; static char *pidfile;
/* This flags signals the message loop of the kernel interface whether it /* This flags signals the message loop of the kernel interface whether it
shall do what it says or just stop. Will be reset by termination_handler. */ shall do what it says or just stop. Will be reset by termination_handler. */
static volatile int keep_on_running = 1; static volatile int keep_on_running = 1;
/* This flag signals that SIGTERM was received. mount.davfs will then /* This flag signals that SIGTERM was received. mount.davfs will then
terminate without uploading dirty files. */ terminate without uploading dirty files. */
skipping to change at line 223 skipping to change at line 234
{ {
setlocale(LC_ALL, ""); setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR); bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE); textdomain(PACKAGE);
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), PACKAGE_STRING); syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), PACKAGE_STRING);
dav_args *args = parse_commandline(argc, argv); dav_args *args = parse_commandline(argc, argv);
if (geteuid() != 0) if (geteuid() != 0)
error(EXIT_FAILURE, errno, _("program is not setuid root")); ERR(_("program is not setuid root"));
if (seteuid(getuid()) != 0) if (seteuid(getuid()) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (getuid() != 0) if (getuid() != 0)
check_fstab(args); check_fstab(args);
parse_config(args); parse_config(args);
check_dirs(args); check_dirs(args);
check_permissions(args); check_permissions(args);
skipping to change at line 271 skipping to change at line 282
"Parent: writing mtab entry"); "Parent: writing mtab entry");
write_mtab_entry(args); write_mtab_entry(args);
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Parent: leaving now"); syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Parent: leaving now");
delete_args(args); delete_args(args);
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
} else if (childpid < 0) { } else if (childpid < 0) {
delete_args(args); delete_args(args);
error(EXIT_FAILURE, errno, _("can't start daemon process")); ERR(_("can't start daemon process"));
} }
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Set signal handler"); syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Set signal handler");
struct sigaction action; struct sigaction action;
action.sa_handler = termination_handler; action.sa_handler = termination_handler;
sigemptyset(&action.sa_mask); sigemptyset(&action.sa_mask);
sigaddset(&action.sa_mask, SIGTERM); sigaddset(&action.sa_mask, SIGTERM);
sigaddset(&action.sa_mask, SIGHUP); sigaddset(&action.sa_mask, SIGHUP);
action.sa_flags = 0; action.sa_flags = 0;
sigaction(SIGTERM, &action, NULL); sigaction(SIGTERM, &action, NULL);
sigaction(SIGHUP, &action, NULL); sigaction(SIGHUP, &action, NULL);
int ret = 0; int ret = 0;
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Releasing root privileges"); syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "Releasing root privileges");
uid_t daemon_id = geteuid(); uid_t daemon_id = geteuid();
if (seteuid(0) != 0) if (seteuid(0) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
ret = setuid(daemon_id); ret = setuid(daemon_id);
if (ret) { if (ret) {
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_ERR), syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_ERR),
_("can't release root privileges")); _("can't release root privileges"));
kill(getppid(), SIGHUP); kill(getppid(), SIGHUP);
} }
time_t idle_time = args->delay_upload; time_t idle_time = args->delay_upload;
if (!idle_time) if (!idle_time)
idle_time = DAV_DELAY_UPLOAD; idle_time = DAV_DELAY_UPLOAD;
skipping to change at line 390 skipping to change at line 401
/*===================*/ /*===================*/
/* Changes the group id of the process permanently to dav_group. The /* Changes the group id of the process permanently to dav_group. The
effective user id of the process will be changed too, but the real effective user id of the process will be changed too, but the real
user id still has to be changed permanently. */ user id still has to be changed permanently. */
static void static void
change_persona(dav_args *args) change_persona(dav_args *args)
{ {
struct group *grp = getgrnam(args->dav_group); struct group *grp = getgrnam(args->dav_group);
if (!grp) if (!grp)
error(EXIT_FAILURE, errno, _("group %s does not exist"), ERR(_("group %s does not exist"),
args->dav_group); args->dav_group);
if (seteuid(0) != 0) if (seteuid(0) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (setgid(grp->gr_gid) != 0) if (setgid(grp->gr_gid) != 0)
error(EXIT_FAILURE, errno, _("can't change group id")); ERR(_("can't change group id"));
if (getuid() == 0) { if (getuid() == 0) {
struct passwd *pw = getpwnam(args->dav_user); struct passwd *pw = getpwnam(args->dav_user);
if (!pw) if (!pw)
error(EXIT_FAILURE, errno, _("user %s does not exist"), ERR(_("user %s does not exist"),
args->dav_user); args->dav_user);
if (seteuid(pw->pw_uid) != 0) if (seteuid(pw->pw_uid) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
} else { } else {
if (seteuid(getuid()) != 0) if (seteuid(getuid()) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
} }
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
"changing persona: euid %i, gid %i", geteuid(), getgid()); "changing persona: euid %i, gid %i", geteuid(), getgid());
} }
/* Checks for the existence of necessary and usefull directories and files. /* Checks for the existence of necessary and usefull directories and files.
- checks whether it can use the proc file system for information about - checks whether it can use the proc file system for information about
mounted file systems, or has to use mtab mounted file systems, or has to use mtab
- whether the directory to save pid files exists and has correct owner and - whether the directory to save pid files exists and has correct owner and
permissions; if not it tries to create it and/or set owner and permissions permissions; if not it tries to create it and/or set owner and permissions
- when invoked by non-root user: checks for configuration directory in the - when invoked by non-root user: checks for configuration directory in the
users homepage and creates missing directories and files users homepage and creates missing directories and files
- checks wether args->cache_dir is accessible. */ - checks wether args->cache_dir is accessible. */
static void static void
check_dirs(dav_args *args) check_dirs(dav_args *args)
{ {
struct stat st; struct stat st;
#ifdef __linux__
if (lstat(_PATH_MOUNTED, &st) != 0) if (lstat(_PATH_MOUNTED, &st) != 0)
error(EXIT_FAILURE, errno, _("can't access file %s"), _PATH_MOUNTED); ERR(_("can't access file %s"), _PATH_MOUNTED);
int mtab_is_link = S_ISLNK(st.st_mode); int mtab_is_link = S_ISLNK(st.st_mode);
if (stat(DAV_MOUNTS, &st) == 0) { if (stat(DAV_MOUNTS, &st) == 0) {
mounts = DAV_MOUNTS; mounts = DAV_MOUNTS;
args->use_utab = mtab_is_link; args->use_utab = mtab_is_link;
} else { } else {
mounts = _PATH_MOUNTED; mounts = _PATH_MOUNTED;
} }
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "mounts in: %s", mounts); syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "mounts in: %s", mounts);
if (args->use_utab) { if (args->use_utab) {
char *utab_dir = NULL; char *utab_dir = NULL;
if (asprintf(&utab_dir,"%s/%s", DAV_LOCALSTATE_DIR, DAV_UTAB_DIR) < 0) if (asprintf(&utab_dir,"%s/%s", DAV_LOCALSTATE_DIR, DAV_UTAB_DIR) < 0)
abort(); abort();
if (stat(utab_dir, &st) != 0) { if (stat(utab_dir, &st) != 0) {
if (seteuid(0) != 0) if (seteuid(0) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (mkdir(utab_dir, S_IRWXU | S_IRGRP | S_IXGRP if (mkdir(utab_dir, S_IRWXU | S_IRGRP | S_IXGRP
| S_IROTH | S_IXOTH) == 0) { | S_IROTH | S_IXOTH) == 0) {
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " and %s/%s", syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), " and %s/%s",
utab_dir, DAV_UTAB); utab_dir, DAV_UTAB);
} else { } else {
error(0, errno, _("can't create directory %s"), utab_dir); WARN(_("can't create directory %s"), utab_dir);
} }
if (seteuid(getuid()) != 0) if (seteuid(getuid()) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
} }
free(utab_dir); free(utab_dir);
} }
#endif
if (seteuid(0) != 0) if (seteuid(0) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (stat(DAV_SYS_RUN, &st) != 0) { if (stat(DAV_SYS_RUN, &st) != 0) {
if (mkdir(DAV_SYS_RUN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH | S_ISVTX) if (mkdir(DAV_SYS_RUN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH | S_ISVTX)
!= 0 && errno != EEXIST) != 0 && errno != EEXIST)
error(EXIT_FAILURE, errno, _("can't create directory %s"), ERR(_("can't create directory %s"),
DAV_SYS_RUN); DAV_SYS_RUN);
} }
if (stat(DAV_SYS_RUN, &st) != 0) if (stat(DAV_SYS_RUN, &st) != 0)
error(EXIT_FAILURE, errno, _("can't access directory %s"), ERR(_("can't access directory %s"),
DAV_SYS_RUN); DAV_SYS_RUN);
if ((st.st_mode & (S_IRWXG | S_ISVTX)) != (S_IRWXG | S_ISVTX)) { if ((st.st_mode & (S_IRWXG | S_ISVTX)) != (S_IRWXG | S_ISVTX)) {
if (chmod(DAV_SYS_RUN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH | S_ISVTX) if (chmod(DAV_SYS_RUN, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH | S_ISVTX)
!= 0) != 0)
error(EXIT_FAILURE, errno, ERR(_("can't change mode of directory %s"), DAV_SYS_RUN);
_("can't change mode of directory %s"), DAV_SYS_RUN);
} }
struct group *grp = getgrnam(args->dav_group); struct group *grp = getgrnam(args->dav_group);
if (!grp) if (!grp)
error(EXIT_FAILURE, errno, _("group %s does not exist"), ERR(_("group %s does not exist"),
args->dav_group); args->dav_group);
if (st.st_gid != grp->gr_gid) { if (st.st_gid != grp->gr_gid) {
if (chown(DAV_SYS_RUN, 0, grp->gr_gid) != 0) if (chown(DAV_SYS_RUN, 0, grp->gr_gid) != 0)
error(EXIT_FAILURE, errno, ERR(_("can't change group of directory %s"), DAV_SYS_RUN);
_("can't change group of directory %s"), DAV_SYS_RUN);
} }
if (seteuid(getuid()) != 0) if (seteuid(getuid()) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (getuid() != 0) { if (getuid() != 0) {
char *path = NULL; char *path = NULL;
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_dir) if (pw && pw->pw_dir)
path = ne_concat(pw->pw_dir, "/.", PACKAGE, NULL); path = ne_concat(pw->pw_dir, "/.", PACKAGE, NULL);
if (path && stat(path, &st) != 0) if (path && stat(path, &st) != 0)
mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
skipping to change at line 539 skipping to change at line 550
free(template); free(template);
} }
free(file_name); free(file_name);
} }
free(path); free(path);
} }
if (strcmp(args->cache_dir, args->sys_cache) == 0) { if (strcmp(args->cache_dir, args->sys_cache) == 0) {
if (seteuid(0) != 0) if (seteuid(0) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (stat(args->sys_cache, &st) != 0) { if (stat(args->sys_cache, &st) != 0) {
if (mkdir(args->sys_cache, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) if (mkdir(args->sys_cache, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
!= 0) != 0)
error(EXIT_FAILURE, errno, _("can't create directory %s"), ERR(_("can't create directory %s"),
args->sys_cache); args->sys_cache);
} }
if (stat(args->sys_cache, &st) != 0) if (stat(args->sys_cache, &st) != 0)
error(EXIT_FAILURE, errno, _("can't access directory %s"), ERR(_("can't access directory %s"),
args->sys_cache); args->sys_cache);
if ((st.st_mode & S_IRWXG) != S_IRWXG) { if ((st.st_mode & S_IRWXG) != S_IRWXG) {
if (chmod(args->sys_cache, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) if (chmod(args->sys_cache, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
!= 0) != 0)
error(EXIT_FAILURE, errno, ERR(_("can't change mode of directory %s"),
_("can't change mode of directory %s"),
args->sys_cache); args->sys_cache);
} }
struct group *grp = getgrnam(args->dav_group); struct group *grp = getgrnam(args->dav_group);
if (!grp) if (!grp)
error(EXIT_FAILURE, errno, _("group %s does not exist"), ERR(_("group %s does not exist"),
args->dav_group); args->dav_group);
if (st.st_gid != grp->gr_gid) { if (st.st_gid != grp->gr_gid) {
if (chown(args->sys_cache, 0, grp->gr_gid) != 0) if (chown(args->sys_cache, 0, grp->gr_gid) != 0)
error(EXIT_FAILURE, errno, ERR(_("can't change group of directory %s"),
_("can't change group of directory %s"),
args->sys_cache); args->sys_cache);
} }
if (seteuid(getuid()) != 0) if (seteuid(getuid()) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
} else { } else {
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
if (!pw) if (!pw)
error(EXIT_FAILURE, errno, _("can't read user data base")); ERR(_("can't read user data base"));
if (!pw->pw_name) if (!pw->pw_name)
error(EXIT_FAILURE, 0, _("can't read user data base")); ERR(_("can't read user data base"));
if (stat(args->cache_dir, &st) != 0) { if (stat(args->cache_dir, &st) != 0) {
if (mkdir(args->cache_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) if (mkdir(args->cache_dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH)
!= 0) != 0)
error(EXIT_FAILURE, errno, _("can't create directory %s"), ERR(_("can't create directory %s"),
args->cache_dir); args->cache_dir);
} }
if (stat(args->cache_dir, &st) != 0) if (stat(args->cache_dir, &st) != 0)
error(EXIT_FAILURE, errno, _("can't access directory %s"), ERR(_("can't access directory %s"),
args->cache_dir); args->cache_dir);
if ((st.st_uid != getuid() || (st.st_mode & S_IRWXU) != S_IRWXU) if ((st.st_uid != getuid() || (st.st_mode & S_IRWXU) != S_IRWXU)
&& (st.st_mode & S_IRWXO) != S_IRWXO) { && (st.st_mode & S_IRWXO) != S_IRWXO) {
if ((st.st_mode & S_IRWXG) != S_IRWXG) if ((st.st_mode & S_IRWXG) != S_IRWXG)
error(EXIT_FAILURE, errno, _("can't access directory %s"), ERR(_("can't access directory %s"),
args->cache_dir); args->cache_dir);
struct group *grp = getgrgid(st.st_gid); struct group *grp = getgrgid(st.st_gid);
if (!grp) if (!grp)
error(EXIT_FAILURE, errno, _("can't read group data base")); ERR(_("can't read group data base"));
char **members = grp->gr_mem; char **members = grp->gr_mem;
while (*members && strcmp(*members, pw->pw_name) != 0) while (*members && strcmp(*members, pw->pw_name) != 0)
members++; members++;
if (!*members) if (!*members)
error(EXIT_FAILURE, 0, _("can't access directory %s"), ERR(_("can't access directory %s"),
args->cache_dir); args->cache_dir);
} }
} }
} }
/* Checks whether url is already mounted on mpoint, creates the name of the /* Checks whether url is already mounted on mpoint, creates the name of the
pid file and checks whether it already exists. pid file and checks whether it already exists.
If one of these tests is positive, it prints an error message and If one of these tests is positive, it prints an error message and
terminates the program. Otherwise it returns the name of the pid file. terminates the program. Otherwise it returns the name of the pid file.
return value : the name of the pid file. */ return value : the name of the pid file. */
static char * static char *
check_double_mounts(dav_args *args) check_double_mounts(dav_args *args)
{ {
FILE *mtab = setmntent(mounts, "r"); if (is_mounted()) {
if (!mtab) ERR(_("%s is already mounted on %s"), url,
error(EXIT_FAILURE, errno, _("can't open file %s"), mounts); mpoint);
struct mntent *mt = getmntent(mtab);
while (mt) {
if (strcmp(mpoint, mt->mnt_dir) == 0
&& strcmp(url, mt->mnt_fsname) == 0)
error(EXIT_FAILURE, 0, _("%s is already mounted on %s"), url,
mpoint);
mt = getmntent(mtab);
} }
endmntent(mtab);
char *m = mpoint; char *m = mpoint;
while (*m == '/') while (*m == '/')
m++; m++;
char *mp = ne_strdup(m); char *mp = ne_strdup(m);
m = strchr(mp, '/'); m = strchr(mp, '/');
while (m) { while (m) {
*m = '-'; *m = '-';
m = strchr(mp, '/'); m = strchr(mp, '/');
} }
char *pidf = NULL; char *pidf = NULL;
if (asprintf(&pidf, "%s/%s.pid", DAV_SYS_RUN, mp) < 0) abort(); if (asprintf(&pidf, "%s/%s.pid", DAV_SYS_RUN, mp) < 0) abort();
free(mp); free(mp);
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "PID file: %s", pidf); syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "PID file: %s", pidf);
FILE *file = fopen(pidf, "r"); FILE *file = fopen(pidf, "r");
if (file) if (file)
error(EXIT_FAILURE, 0, _("found PID file %s.\n" ERR(_("found PID file %s.\n"
"Either %s is used by another process,\n" "Either %s is used by another process,\n"
"or another mount process ended irregular"), pidf, mpoint); "or another mount process ended irregular"), pidf, mpoint);
return pidf; return pidf;
} }
/* Checks fstab whether there is an entry for the mountpoint specified in args /* Checks fstab whether there is an entry for the mountpoint specified in args
and compares the values in args with the values in fstab. and compares the values in args with the values in fstab.
If there is no such entry, or this entry does not allow user-mount, or the If there is no such entry, or this entry does not allow user-mount, or the
values differ, an error message is printed and the program terminates. */ values differ, an error message is printed and the program terminates. */
static void static void
check_fstab(const dav_args *args) check_fstab(const dav_args *args)
{ {
dav_args *n_args = new_args(); dav_args *n_args;
n_args->mopts = DAV_USER_MOPTS; struct fstab *ft;
FILE *fstab = setmntent(_PATH_MNTTAB, "r"); #ifdef __FreeBSD__
if (!fstab) int status;
error(EXIT_FAILURE, errno, _("can't open file %s"), _PATH_MNTTAB); int val;
size_t val_len = sizeof(int);
struct mntent *ft = getmntent(fstab);
while (ft) { status = sysctlbyname (VFS_USERMOUNT, &val, &val_len, NULL, 0);
if (ft->mnt_dir) {
char *mp = canonicalize_file_name(ft->mnt_dir); if (status != 0) {
WARN(_("sysctl on " VFS_USERMOUNT " failed"));
} else if (val == 1) {
/* User mount is set, allow user mouting */
return;
}
#endif
if (setfsent() == 0)
ERR(_("can't open file %s"), _PATH_FSTAB);
while ((ft = getfsent()) != NULL) {
if (ft->fs_file) {
char *mp = mcanonicalize_file_name(ft->fs_file);
if (mp) { if (mp) {
if (strcmp(mp, mpoint) == 0) { if (strcmp(mp, mpoint) == 0) {
free(mp); free(mp);
break; break;
} }
free(mp); free(mp);
} }
} }
ft = getmntent(fstab);
} }
(void) endfsent();
if (!ft) if (!ft)
error(EXIT_FAILURE, 0, _("no entry for %s found in %s"), mpoint, ERR(_("no entry for %s found in %s"), mpoint,
_PATH_MNTTAB); _PATH_FSTAB);
if (strcmp(url, ft->mnt_fsname) != 0) { if (strcmp(url, ft->fs_spec) != 0) {
error(EXIT_FAILURE, 0, _("different URL in %s"), _PATH_MNTTAB); ERR(_("different URL in %s"), _PATH_FSTAB);
} }
if (!ft->mnt_type || strcmp(DAV_FS_TYPE, ft->mnt_type) != 0) if (!ft->fs_vfstype || strcmp(DAV_FS_TYPE, ft->fs_vfstype) != 0)
error(EXIT_FAILURE, 0, _("different file system type in %s"), ERR(_("different file system type in %s %s %s"), ft->fs_vfstype, DAV_FS_
_PATH_MNTTAB); TYPE,
_PATH_FSTAB);
if (ft->mnt_opts) n_args = new_args();
get_options(n_args, ft->mnt_opts); n_args->mopts = DAV_USER_MOPTS;
endmntent(fstab); if (ft->fs_mntops)
get_options(n_args, ft->fs_mntops);
if (args->conf || n_args->conf) { if (args->conf || n_args->conf) {
if (!args->conf || !n_args->conf if (!args->conf || !n_args->conf
|| strcmp(args->conf, n_args->conf) != 0) || strcmp(args->conf, n_args->conf) != 0)
error(EXIT_FAILURE, 0, _("different config file in %s"), ERR(_("different config file in %s"),
_PATH_MNTTAB); _PATH_FSTAB);
} }
if (args->cl_username || n_args->cl_username) { if (args->cl_username || n_args->cl_username) {
if (!args->cl_username || !n_args->cl_username if (!args->cl_username || !n_args->cl_username
|| strcmp(args->cl_username, n_args->cl_username) != 0) || strcmp(args->cl_username, n_args->cl_username) != 0)
error(EXIT_FAILURE, 0, _("different username in %s"), _PATH_MNTTAB); ERR(_("different username in %s"), _PATH_FSTAB);
} }
if (!n_args->user && !n_args->users) if (!n_args->user && !n_args->users)
error(EXIT_FAILURE, 0, ERR(_("neither option `user' nor option `users' set in %s"),
_("neither option `user' nor option `users' set in %s"), _PATH_FSTAB);
_PATH_MNTTAB);
if (args->mopts != n_args->mopts || args->grpid != n_args->grpid) if (args->mopts != n_args->mopts || args->grpid != n_args->grpid)
error(EXIT_FAILURE, 0, _("different mount options in %s"), ERR(_("different mount options in %s"),
_PATH_MNTTAB); _PATH_FSTAB);
if (args->uid != n_args->uid) if (args->uid != n_args->uid)
error(EXIT_FAILURE, 0, _("different uid in %s"), _PATH_MNTTAB); ERR(_("different uid in %s"), _PATH_FSTAB);
if (args->gid != n_args->gid) if (args->gid != n_args->gid)
error(EXIT_FAILURE, 0, _("different gid in %s"), _PATH_MNTTAB); ERR(_("different gid in %s"), _PATH_FSTAB);
if (args->dir_mode != n_args->dir_mode) if (args->dir_mode != n_args->dir_mode)
error(EXIT_FAILURE, 0, _("different dir_mode in %s"), _PATH_MNTTAB); ERR(_("different dir_mode in %s"), _PATH_FSTAB);
if (args->file_mode != n_args->file_mode) if (args->file_mode != n_args->file_mode)
error(EXIT_FAILURE, 0, _("different file_mode in %s"), _PATH_MNTTAB); ERR(_("different file_mode in %s"), _PATH_FSTAB);
delete_args(n_args); delete_args(n_args);
} }
/* The mounting user must be either root or meet the following conditions: /* The mounting user must be either root or meet the following conditions:
- The uid must not differ from the option uid, if this option is used. - The uid must not differ from the option uid, if this option is used.
- The user must belong to the group specified in option gid (if used). - The user must belong to the group specified in option gid (if used).
- The user must be member of group args->dav_group. - The user must be member of group args->dav_group.
If this conditions are not met or an error occurs, an error message is If this conditions are not met or an error occurs, an error message is
printed and exit(EXIT_FAILURE) is called. */ printed and exit(EXIT_FAILURE) is called. */
static void static void
check_permissions(dav_args *args) check_permissions(dav_args *args)
{ {
if (getuid() == 0) if (getuid() == 0)
return; return;
if (args->uid != getuid()) if (args->uid != getuid())
error(EXIT_FAILURE, 0, ERR(_("you can't set file owner different from your uid"));
_("you can't set file owner different from your uid"));
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "uid ok"); syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "uid ok");
if (getgid() != args->gid) { if (getgid() != args->gid) {
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
if (!pw) if (!pw)
error(EXIT_FAILURE, errno, _("can't read user data base")); ERR(_("can't read user data base"));
if (!pw->pw_name) if (!pw->pw_name)
error(EXIT_FAILURE, 0, _("can't read user data base")); ERR(_("can't read user data base"));
struct group *grp = getgrgid(args->gid); struct group *grp = getgrgid(args->gid);
if (!grp) if (!grp)
error(EXIT_FAILURE, 0, _("can't read group data base")); ERR(_("can't read group data base"));
char **members = grp->gr_mem; char **members = grp->gr_mem;
while (*members && strcmp(*members, pw->pw_name) != 0) while (*members && strcmp(*members, pw->pw_name) != 0)
members++; members++;
if (!*members) if (!*members)
error(EXIT_FAILURE, 0, ERR(_("you must be member of the group of the file system"));
_("you must be member of the group of the file system"));
} }
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "gid ok"); syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), "gid ok");
struct passwd *pw; struct passwd *pw;
pw = getpwuid(getuid()); pw = getpwuid(getuid());
if (!pw) if (!pw)
error(EXIT_FAILURE, errno, _("can't read user data base")); ERR(_("can't read user data base"));
if (!pw->pw_name) if (!pw->pw_name)
error(EXIT_FAILURE, 0, _("can't read user data base")); ERR(_("can't read user data base"));
struct group *grp = getgrnam(args->dav_group); struct group *grp = getgrnam(args->dav_group);
if (!grp) if (!grp)
error(EXIT_FAILURE, errno, _("group %s does not exist"), ERR(_("group %s does not exist"),
args->dav_group); args->dav_group);
if (pw->pw_gid != grp->gr_gid) { if (pw->pw_gid != grp->gr_gid) {
int ngroups = getgroups(0, NULL); int ngroups = getgroups(0, NULL);
gid_t *groups = NULL; gid_t *groups = NULL;
if (ngroups > 0) { if (ngroups > 0) {
groups = (gid_t *) malloc(ngroups * sizeof(gid_t)); groups = (gid_t *) malloc(ngroups * sizeof(gid_t));
if (!groups) abort(); if (!groups) abort();
if (getgroups(ngroups, groups) < 0) if (getgroups(ngroups, groups) < 0)
error(EXIT_FAILURE, 0, _("can't read group data base")); ERR(_("can't read group data base"));
} else { } else {
error(EXIT_FAILURE, 0, _("can't read group data base")); ERR(_("can't read group data base"));
} }
int i; int i;
for (i = 0; i < ngroups; i++) { for (i = 0; i < ngroups; i++) {
if (grp->gr_gid == groups[i]) if (grp->gr_gid == groups[i])
break; break;
} }
free(groups); free(groups);
if (i == ngroups) if (i == ngroups)
error(EXIT_FAILURE, 0, _("user %s must be member of group %s"), ERR(_("user %s must be member of group %s"),
pw->pw_name, grp->gr_name); pw->pw_name, grp->gr_name);
} }
if (args->debug & DAV_DBG_CONFIG) if (args->debug & DAV_DBG_CONFIG)
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG), syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_DEBUG),
"memeber of group %s", args->dav_group); "memeber of group %s", args->dav_group);
} }
/* Checks wether the file system is mounted. /* Checks wether the file system is mounted.
It uses information from the private global variables mounts (mtab-file), It uses information from the private global variables mounts (mtab-file),
url (must be device in the mtab entry) and mpoint (mount point). url (must be device in the mtab entry) and mpoint (mount point).
return value : 0 - no matching entry in the mtab-file (not mounted) return value : 0 - no matching entry in the mtab-file (not mounted)
1 - matching entry in the mtab-file (mounted) */ 1 - matching entry in the mtab-file (mounted) */
static int #ifdef __FreeBSD__
is_mounted(void) static int is_mounted_freebsd(void)
{
static struct statfs *sfsbuf;
size_t sfsbufsize;
int mntsize;
int i;
int found = 0;
mntsize = getfsstat(NULL, 0, MNT_NOWAIT);
if (mntsize > 0) {
sfsbufsize = (mntsize + 1) * sizeof(struct statfs);
if ((sfsbuf = malloc(sfsbufsize)) == NULL)
ERR("malloc");
mntsize = getfsstat(sfsbuf, (long)sfsbufsize, MNT_NOWAIT);
for (i = 0; i < mntsize; i++) {
struct statfs *sfs;
sfs = &sfsbuf[i];
if (strcmp(mpoint, sfs->f_mntonname) == 0
&& strcmp(url, sfs->f_mntfromname) == 0) {
found = 1;
break;
}
}
}
free(sfsbuf);
return found;
}
#endif
#ifdef __linux__
static int is_mounted_linux(void)
{ {
int found = 0; int found = 0;
FILE *mtab = setmntent(mounts, "r"); FILE *mtab = setmntent(mounts, "r");
if (mtab) { if (mtab) {
struct mntent *mt = getmntent(mtab); struct mntent *mt = getmntent(mtab);
while (mt && !found) { while (mt && !found) {
if (strcmp(mpoint, mt->mnt_dir) == 0 if (strcmp(mpoint, mt->mnt_dir) == 0
&& strcmp(url, mt->mnt_fsname) == 0) && strcmp(url, mt->mnt_fsname) == 0)
found = 1; found = 1;
mt = getmntent(mtab); mt = getmntent(mtab);
} }
} }
endmntent(mtab); endmntent(mtab);
return found; return found;
} }
#endif
static int
is_mounted(void)
{
#ifdef __linux__
return is_mounted_linux();
#elif __FreeBSD__
return is_mounted_freebsd();
#else
return 0;
#endif
}
/* Parses commandline arguments and options and stores them in args and the /* Parses commandline arguments and options and stores them in args and the
private global variables url and mpoint. private global variables url and mpoint.
For arguments and options please see the usage()-funktion. For arguments and options please see the usage()-funktion.
As soon as 'version' or 'help' is found, an appropriate message is printed As soon as 'version' or 'help' is found, an appropriate message is printed
and exit(EXIT_SUCCESS) is called. and exit(EXIT_SUCCESS) is called.
If it does not find exactly two non-option-arguments (url and mointpoint) If it does not find exactly two non-option-arguments (url and mointpoint)
it prints an error message and calls exit(EXIT_FAILURE). it prints an error message and calls exit(EXIT_FAILURE).
argc : the number of arguments. argc : the number of arguments.
argv[] : array of argument strings. argv[] : array of argument strings.
skipping to change at line 884 skipping to change at line 939
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
case 'o': case 'o':
get_options(args, optarg); get_options(args, optarg);
break; break;
case 'n': case 'n':
case 'v': case 'v':
case 'w': case 'w':
case '?': case '?':
break; break;
default: default:
error(EXIT_FAILURE, 0, _("unknown error parsing arguments")); ERR(_("unknown error parsing arguments"));
} }
o = getopt_long(argc, argv, short_options, options, NULL); o = getopt_long(argc, argv, short_options, options, NULL);
} }
i = optind; i = optind;
switch (argc - i) { switch (argc - i) {
case 0: case 0:
case 1: case 1:
error(0, 0, _("missing argument")); WARN(_("missing argument"));
usage(); usage();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
case 2: case 2:
if (*argv[i] == '\"' || *argv[i] == '\'') { if (*argv[i] == '\"' || *argv[i] == '\'') {
url = ne_strndup(argv[i] + 1, strlen(argv[i]) -2); url = ne_strndup(argv[i] + 1, strlen(argv[i]) -2);
} else { } else {
url = ne_strdup(argv[i]); url = ne_strdup(argv[i]);
} }
i++; i++;
mpoint = canonicalize_file_name(argv[i]); mpoint = mcanonicalize_file_name(argv[i]);
if (!mpoint) if (!mpoint)
error(EXIT_FAILURE, 0, ERR(_("can't evaluate path of mount point %s"), mpoint);
_("can't evaluate path of mount point %s"), mpoint);
break; break;
default: default:
error(0, 0, _("too many arguments")); WARN(_("too many arguments"));
usage(); usage();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
if (getuid() != 0 && *argv[i] != '/') { if (getuid() != 0 && *argv[i] != '/') {
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
if (!pw || !pw->pw_dir) if (!pw || !pw->pw_dir)
error(EXIT_FAILURE, 0, ERR(_("can't get home directory for uid %i"), getuid());
_("can't get home directory for uid %i"), getuid());
if (strstr(mpoint, pw->pw_dir) != mpoint) if (strstr(mpoint, pw->pw_dir) != mpoint)
error(EXIT_FAILURE, 0, _("A relative mount point must lie " ERR(_("A relative mount point must lie "
"within your home directory")); "within your home directory"));
} }
if (!url) if (!url)
error(EXIT_FAILURE, 0, _("no WebDAV-server specified")); ERR(_("no WebDAV-server specified"));
if (split_uri(&args->scheme, &args->host, &args->port, &args->path, if (split_uri(&args->scheme, &args->host, &args->port, &args->path,
url) != 0) url) != 0)
error(EXIT_FAILURE, 0, _("invalid URL")); ERR(_("invalid URL"));
if (!args->port) if (!args->port)
args->port = ne_uri_defaultport(args->scheme); args->port = ne_uri_defaultport(args->scheme);
return args; return args;
} }
/* Reads and parses the configuration files and stores the values in args. /* Reads and parses the configuration files and stores the values in args.
The system wide configuration file is parsed first. If args->conf is The system wide configuration file is parsed first. If args->conf is
given it will be parsed too and overwrites the values from the system given it will be parsed too and overwrites the values from the system
wide configuration file. */ wide configuration file. */
static void static void
parse_config(dav_args *args) parse_config(dav_args *args)
{ {
read_config(args, DAV_SYS_CONF_DIR "/" DAV_CONFIG, 1); read_config(args, DAV_SYS_CONF_DIR "/" DAV_CONFIG, 1);
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
if (!pw || !pw->pw_dir) if (!pw || !pw->pw_dir)
error(EXIT_FAILURE, 0, _("can't determine home directory")); ERR(_("can't determine home directory"));
if (args->conf) { if (args->conf) {
if (*args->conf == '~') { if (*args->conf == '~') {
int p = 1; int p = 1;
if (*(args->conf + p) == '/') if (*(args->conf + p) == '/')
p++; p++;
char *f = ne_concat(pw->pw_dir, "/", args->conf + p, NULL); char *f = ne_concat(pw->pw_dir, "/", args->conf + p, NULL);
free(args->conf); free(args->conf);
args->conf = f; args->conf = f;
} }
skipping to change at line 1051 skipping to change at line 1104
} }
if (args->clicert && *args->clicert != '/' && getuid() == 0) { if (args->clicert && *args->clicert != '/' && getuid() == 0) {
char *f = ne_concat(DAV_SYS_CONF_DIR, "/", DAV_CERTS_DIR, "/", char *f = ne_concat(DAV_SYS_CONF_DIR, "/", DAV_CERTS_DIR, "/",
DAV_CLICERTS_DIR, "/", args->clicert, NULL); DAV_CLICERTS_DIR, "/", args->clicert, NULL);
free(args->clicert); free(args->clicert);
args->clicert = f; args->clicert = f;
} }
if (args->clicert) { if (args->clicert) {
struct stat st; struct stat st;
if (seteuid(0) != 0) if (seteuid(0) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (stat(args->clicert, &st) < 0) if (stat(args->clicert, &st) < 0)
error(EXIT_FAILURE, 0, _("can't read client certificate %s"), ERR(_("can't read client certificate %s"),
args->clicert); args->clicert);
if (seteuid(getuid()) != 0) if (seteuid(getuid()) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (st.st_uid != getuid() && st.st_uid != 0) if (st.st_uid != getuid() && st.st_uid != 0)
error(EXIT_FAILURE, 0, ERR(_("client certificate file %s has wrong owner"),
_("client certificate file %s has wrong owner"), args->clicert);
args->clicert);
if ((st.st_mode & if ((st.st_mode &
(S_IXUSR | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX)) (S_IXUSR | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX))
!= 0) != 0)
error(EXIT_FAILURE, 0, ERR(_("client certificate file %s has wrong permissions"),
_("client certificate file %s has wrong permissions"), args->clicert);
args->clicert);
} }
if (getuid() == 0 && !args->p_host) { if (getuid() == 0 && !args->p_host) {
proxy_from_env(args); proxy_from_env(args);
read_no_proxy_list(args); read_no_proxy_list(args);
} }
if (!args->p_host) if (!args->p_host)
args->useproxy = 0; args->useproxy = 0;
skipping to change at line 1099 skipping to change at line 1150
log_dbg_config(args); log_dbg_config(args);
} }
/* Reads the secrets file and asks the user interactivly for credentials if /* Reads the secrets file and asks the user interactivly for credentials if
necessary. The user secrets file is parsed after the system wide secrets necessary. The user secrets file is parsed after the system wide secrets
file, so it will have precedence. */ file, so it will have precedence. */
static void static void
parse_secrets(dav_args *args) parse_secrets(dav_args *args)
{ {
if (seteuid(0) != 0) if (seteuid(0) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
read_secrets(args, DAV_SYS_CONF_DIR "/" DAV_SECRETS); read_secrets(args, DAV_SYS_CONF_DIR "/" DAV_SECRETS);
if (seteuid(getuid()) != 0) if (seteuid(getuid()) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
if (args->secrets) { if (args->secrets) {
read_secrets(args, args->secrets); read_secrets(args, args->secrets);
} }
if (args->cl_username) { if (args->cl_username) {
if (args->username) if (args->username)
free(args->username); free(args->username);
args->username = args->cl_username; args->username = args->cl_username;
args->cl_username = NULL; args->cl_username = NULL;
skipping to change at line 1213 skipping to change at line 1264
got_sigterm = 1; got_sigterm = 1;
} }
/* Adds an entry to _PATH_MOUNTED for the mounted file system. /* Adds an entry to _PATH_MOUNTED for the mounted file system.
If _PATH_MOUNTED is a symbolic link to /proc/mounts it will write an If _PATH_MOUNTED is a symbolic link to /proc/mounts it will write an
entry into /var/run/mount/utab instead. entry into /var/run/mount/utab instead.
If this fails a warning will be printed, but this will not stop mounting. */ If this fails a warning will be printed, but this will not stop mounting. */
static void static void
write_mtab_entry(const dav_args *args) write_mtab_entry(const dav_args *args)
{ {
#ifdef __linux__
struct mntent mntent; struct mntent mntent;
mntent.mnt_opts = NULL; mntent.mnt_opts = NULL;
char *utab_line = NULL; char *utab_line = NULL;
char *tab_file = NULL; char *tab_file = NULL;
char *lock_file = NULL; char *lock_file = NULL;
int privileged = (getuid() == 0); int privileged = (getuid() == 0);
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
if (!pw && !privileged) { if (!pw && !privileged) {
error(0, errno, _("Warning: can't read user data base. Mounting " WARN(_("Warning: can't read user data base. Mounting "
"anyway, but there is no entry in mtab.")); "anyway, but there is no entry in mtab."));
return; return;
} }
char *uid_name = pw->pw_name; char *uid_name = pw->pw_name;
if (args->use_utab) { if (args->use_utab) {
if (asprintf(&utab_line, if (asprintf(&utab_line,
"SRC=%s TARGET=%s ROOT=/ " "SRC=%s TARGET=%s ROOT=/ "
"OPTS=uid=%i,gid=%i%s%s%s%s,helper=%s\n", "OPTS=uid=%i,gid=%i%s%s%s%s,helper=%s\n",
url, mpoint, args->uid, args->gid, url, mpoint, args->uid, args->gid,
(args->grpid) ? ",grpid" : "", (args->grpid) ? ",grpid" : "",
skipping to change at line 1273 skipping to change at line 1325
} }
sigset_t oldset; sigset_t oldset;
sigemptyset(&oldset); sigemptyset(&oldset);
sigset_t newset; sigset_t newset;
sigfillset(&newset); sigfillset(&newset);
sigprocmask(SIG_BLOCK, &newset, &oldset); sigprocmask(SIG_BLOCK, &newset, &oldset);
uid_t orig = geteuid(); uid_t orig = geteuid();
if (seteuid(0) != 0) if (seteuid(0) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
int ld = open(lock_file, O_RDONLY | O_CREAT, int ld = open(lock_file, O_RDONLY | O_CREAT,
S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH); S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
if (!ld) if (!ld)
error(EXIT_FAILURE, errno, _("can't create file %s"), lock_file); ERR(_("can't create file %s"), lock_file);
while (flock(ld, LOCK_EX) != 0) { while (flock(ld, LOCK_EX) != 0) {
if (errno == EAGAIN || errno == EINTR) if (errno == EAGAIN || errno == EINTR)
continue; continue;
error(EXIT_FAILURE, errno, _("can't lock file %s"), lock_file); ERR(_("can't lock file %s"), lock_file);
} }
FILE *tab = NULL; FILE *tab = NULL;
if (args->use_utab) { if (args->use_utab) {
tab = fopen(tab_file, "a"); tab = fopen(tab_file, "a");
} else { } else {
tab = setmntent(tab_file, "a"); tab = setmntent(tab_file, "a");
} }
int err = 0; int err = 0;
if (tab) { if (tab) {
skipping to change at line 1304 skipping to change at line 1356
if (fputs(utab_line, tab) == EOF) if (fputs(utab_line, tab) == EOF)
err = 1; err = 1;
fclose(tab); fclose(tab);
} else { } else {
if (addmntent(tab, &mntent) != 0) if (addmntent(tab, &mntent) != 0)
err = 1; err = 1;
endmntent(tab); endmntent(tab);
} }
} }
if (!tab || err) if (!tab || err)
error(0, 0, _("Warning: can't write entry into %s, but will mount " WARN(_("Warning: can't write entry into %s, but will mount "
"the file system anyway"), tab_file); "the file system anyway"), tab_file);
close(ld); close(ld);
remove(lock_file); remove(lock_file);
if (seteuid(orig) != 0) if (seteuid(orig) != 0)
error(EXIT_FAILURE, errno, _("can't change effective user id")); ERR(_("can't change effective user id"));
sigprocmask(SIG_SETMASK, &oldset, NULL); sigprocmask(SIG_SETMASK, &oldset, NULL);
if (lock_file) if (lock_file)
free(lock_file); free(lock_file);
if (tab_file) if (tab_file)
free(tab_file); free(tab_file);
if (utab_line) if (utab_line)
free(utab_line); free(utab_line);
if (mntent.mnt_opts) if (mntent.mnt_opts)
free(mntent.mnt_opts); free(mntent.mnt_opts);
#endif
} }
/* Helper functions. */ /* Helper functions. */
/* Searches arg from the beginning for digits, valid in base, and converts /* Searches arg from the beginning for digits, valid in base, and converts
them to an integer. If arg does not start with valid digits an error them to an integer. If arg does not start with valid digits an error
message is printed and exit(EXIT_FAILURE) is called. message is printed and exit(EXIT_FAILURE) is called.
Otherwise the integer is returned. Otherwise the integer is returned.
arg : string to be converted arg : string to be converted
base : radix of the number; value between 2 and 36 base : radix of the number; value between 2 and 36
opt : name of the option, arg belongs to. Used in the error message. opt : name of the option, arg belongs to. Used in the error message.
return value: the value of the integer number in arg */ return value: the value of the integer number in arg */
static int static int
arg_to_int(const char *arg, int base, const char *opt) arg_to_int(const char *arg, int base, const char *opt)
{ {
char *tail = NULL; char *tail = NULL;
int n = strtol(arg, &tail, base); int n = strtol(arg, &tail, base);
if (n < 0 || !tail) { if (n < 0 || !tail) {
if (base == 10) { if (base == 10) {
error(EXIT_FAILURE, 0, _("option %s has invalid argument;" ERR(_("option %s has invalid argument;"
"it must be a decimal number"), opt); "it must be a decimal number"), opt);
} else if (base == 8) { } else if (base == 8) {
error(EXIT_FAILURE, 0, _("option %s has invalid argument;" ERR(_("option %s has invalid argument;"
"it must be an octal number"), opt); "it must be an octal number"), opt);
} else { } else {
error(EXIT_FAILURE, 0, _("option %s has invalid argument;" ERR(_("option %s has invalid argument;"
"it must be a number"), opt); "it must be a number"), opt);
} }
} }
return n; return n;
} }
/* Creates a copy of src with name dest. */ /* Creates a copy of src with name dest. */
static void static void
cp_file(const char *src, const char *dest) cp_file(const char *src, const char *dest)
{ {
FILE *in = fopen(src, "r"); FILE *in = fopen(src, "r");
if (!in) if (!in)
error(EXIT_FAILURE, errno, _("can't open file %s"), src); ERR(_("can't open file %s"), src);
FILE *out = fopen(dest, "w"); FILE *out = fopen(dest, "w");
if (!out) if (!out)
error(EXIT_FAILURE, errno, _("can't open file %s"), dest); ERR(_("can't open file %s"), dest);
size_t n = 0; size_t n = 0;
char *line = NULL; char *line = NULL;
int length = getline(&line, &n, in); int length = getline(&line, &n, in);
while (length > 0) { while (length > 0) {
if (fputs(line, out) == EOF) if (fputs(line, out) == EOF)
error(EXIT_FAILURE, errno, _("error writing to file %s"), dest); ERR(_("error writing to file %s"), dest);
length = getline(&line, &n, in); length = getline(&line, &n, in);
} }
if (line) if (line)
free(line); free(line);
fclose(out); fclose(out);
fclose(in); fclose(in);
} }
/* Converts a debug option string s into numerical value. If s is not a /* Converts a debug option string s into numerical value. If s is not a
skipping to change at line 1500 skipping to change at line 1553
args. args.
All strings returned in args are newly allocated, and the calling function All strings returned in args are newly allocated, and the calling function
is responsible to free them. is responsible to free them.
option : a comma separated list of options (like the options in fstab and option : a comma separated list of options (like the options in fstab and
in the -o option of the mount-programm). in the -o option of the mount-programm).
For known options see the declaration at the beginning of the For known options see the declaration at the beginning of the
the function definition. */ the function definition. */
static void static void
get_options(dav_args *args, char *option) get_options(dav_args *args, char *option)
{ {
#ifdef NODEV
#undef NODEV
#endif
enum { enum {
CONF = 0, CONF = 0,
USERNAME, USERNAME,
UID, UID,
GID, GID,
FILE_MODE, FILE_MODE,
DIR_MODE, DIR_MODE,
USER, USER,
NOUSER, NOUSER,
USERS, USERS,
skipping to change at line 1557 skipping to change at line 1613
}; };
int so; int so;
char *argument = NULL; char *argument = NULL;
struct passwd *pwd; struct passwd *pwd;
struct group *grp; struct group *grp;
while (*option != 0) { while (*option != 0) {
so = getsubopt(&option, suboptions, &argument); so = getsubopt(&option, suboptions, &argument);
if ((!argument) && (so < USER)) if ((!argument) && (so < USER))
error(EXIT_FAILURE, 0, ERR(_("option %s requires argument"), suboptions[so]);
_("option %s requires argument"), suboptions[so]);
switch (so) { switch (so) {
case CONF: case CONF:
if (args->conf) if (args->conf)
free(args->conf); free(args->conf);
args->conf = ne_strdup(argument); args->conf = ne_strdup(argument);
break; break;
case USERNAME: case USERNAME:
if (args->cl_username) if (args->cl_username)
free(args->cl_username); free(args->cl_username);
args->cl_username = ne_strdup(argument); args->cl_username = ne_strdup(argument);
skipping to change at line 1652 skipping to change at line 1707
/* Allocates a new dav_args-structure and initializes it. /* Allocates a new dav_args-structure and initializes it.
All members are set to reasonable defaults. */ All members are set to reasonable defaults. */
static dav_args * static dav_args *
new_args(void) new_args(void)
{ {
char *user_dir = NULL; char *user_dir = NULL;
if (getuid() != 0) { if (getuid() != 0) {
struct passwd *pw = getpwuid(getuid()); struct passwd *pw = getpwuid(getuid());
if (!pw) if (!pw)
error(EXIT_FAILURE, errno, _("can't read user data base")); ERR(_("can't read user data base"));
if (!pw->pw_dir) if (!pw->pw_dir)
error(EXIT_FAILURE, 0, _("can't read user data base")); ERR(_("can't read user data base"));
user_dir = ne_concat(pw->pw_dir, "/.", PACKAGE, NULL); user_dir = ne_concat(pw->pw_dir, "/.", PACKAGE, NULL);
} }
dav_args *args = ne_malloc(sizeof(*args)); dav_args *args = ne_malloc(sizeof(*args));
args->cmdline = NULL; args->cmdline = NULL;
args->dav_user = ne_strdup(DAV_USER); args->dav_user = ne_strdup(DAV_USER);
args->dav_group = ne_strdup(DAV_GROUP); args->dav_group = ne_strdup(DAV_GROUP);
if (getuid() != 0) { if (getuid() != 0) {
skipping to change at line 2082 skipping to change at line 2137
while (length > 0) { while (length > 0) {
int parmc = 3; int parmc = 3;
char *parmv[parmc]; char *parmv[parmc];
int count; int count;
count = parse_line(line, parmc, parmv); count = parse_line(line, parmc, parmv);
if (count == 1) { if (count == 1) {
if (*parmv[0] != '[' || *(parmv[0] + strlen(parmv[0]) - 1) != ']') if (*parmv[0] != '[' || *(parmv[0] + strlen(parmv[0]) - 1) != ']')
error_at_line(EXIT_FAILURE, 0, filename, lineno, ERR_AT_LINE(filename, lineno, _("malformed line"));
_("malformed line"));
*(parmv[0] + strlen(parmv[0]) - 1) = '\0'; *(parmv[0] + strlen(parmv[0]) - 1) = '\0';
char *mp = canonicalize_file_name(parmv[0] + 1); char *mp = mcanonicalize_file_name(parmv[0] + 1);
if (mp) { if (mp) {
applies = (strcmp(mp, mpoint) == 0); applies = (strcmp(mp, mpoint) == 0);
free(mp); free(mp);
} }
} else if (applies && count == 2) { } else if (applies && count == 2) {
if (system && strcmp(parmv[0], "dav_user") == 0) { if (system && strcmp(parmv[0], "dav_user") == 0) {
if (args->dav_user) if (args->dav_user)
free(args->dav_user); free(args->dav_user);
skipping to change at line 2123 skipping to change at line 2177
if (args->secrets) if (args->secrets)
free(args->secrets); free(args->secrets);
args->secrets = ne_strdup(parmv[1]); args->secrets = ne_strdup(parmv[1]);
} else if (strcmp(parmv[0], "clientcert") == 0) { } else if (strcmp(parmv[0], "clientcert") == 0) {
if (args->clicert) if (args->clicert)
free(args->clicert); free(args->clicert);
args->clicert = ne_strdup(parmv[1]); args->clicert = ne_strdup(parmv[1]);
} else if (system && strcmp(parmv[0], "proxy") == 0) { } else if (system && strcmp(parmv[0], "proxy") == 0) {
if (split_uri(NULL, &args->p_host, &args->p_port, NULL, if (split_uri(NULL, &args->p_host, &args->p_port, NULL,
parmv[1]) != 0) parmv[1]) != 0)
error_at_line(EXIT_FAILURE, 0, filename, lineno, ERR_AT_LINE(filename, lineno, _("malformed line"));
_("malformed line"));
} else if (system && strcmp(parmv[0], "use_proxy") == 0) { } else if (system && strcmp(parmv[0], "use_proxy") == 0) {
args->useproxy = arg_to_int(parmv[1], 10, parmv[0]); args->useproxy = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "ask_auth") == 0) { } else if (strcmp(parmv[0], "ask_auth") == 0) {
args->askauth = arg_to_int(parmv[1], 10, parmv[0]); args->askauth = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "use_locks") == 0) { } else if (strcmp(parmv[0], "use_locks") == 0) {
args->locks = arg_to_int(parmv[1], 10, parmv[0]); args->locks = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "lock_owner") == 0) { } else if (strcmp(parmv[0], "lock_owner") == 0) {
if (args->lock_owner) if (args->lock_owner)
free(args->lock_owner); free(args->lock_owner);
args->lock_owner = ne_strdup(parmv[1]); args->lock_owner = ne_strdup(parmv[1]);
skipping to change at line 2161 skipping to change at line 2214
} else if (strcmp(parmv[0], "use_compression") == 0) { } else if (strcmp(parmv[0], "use_compression") == 0) {
args->use_compression = arg_to_int(parmv[1], 10, parmv[0]); args->use_compression = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "min_propset") == 0) { } else if (strcmp(parmv[0], "min_propset") == 0) {
args->min_propset = arg_to_int(parmv[1], 10, parmv[0]); args->min_propset = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "follow_redirect") == 0) { } else if (strcmp(parmv[0], "follow_redirect") == 0) {
args->follow_redirect = arg_to_int(parmv[1], 10, parmv[0]); args->follow_redirect = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "sharepoint_href_bug") == 0) { } else if (strcmp(parmv[0], "sharepoint_href_bug") == 0) {
#if NE_VERSION_MAJOR > 0 || NE_VERSION_MINOR > 30 #if NE_VERSION_MAJOR > 0 || NE_VERSION_MINOR > 30
args->sharepoint_href_bug = arg_to_int(parmv[1], 10, parmv[0]); args->sharepoint_href_bug = arg_to_int(parmv[1], 10, parmv[0]);
#else #else
error(EXIT_FAILURE, 0, _("Option sharepoint_href_bug requires " ERR(_("Option sharepoint_href_bug requires "
"Neon version 0.31 or newer")); "Neon version 0.31 or newer"));
#endif #endif
} else if (strcmp(parmv[0], "connect_timeout") == 0) { } else if (strcmp(parmv[0], "connect_timeout") == 0) {
args->connect_timeout = arg_to_int(parmv[1], 10, parmv[0]); args->connect_timeout = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "read_timeout") == 0) { } else if (strcmp(parmv[0], "read_timeout") == 0) {
args->read_timeout = arg_to_int(parmv[1], 10, parmv[0]); args->read_timeout = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "retry") == 0) { } else if (strcmp(parmv[0], "retry") == 0) {
args->retry = arg_to_int(parmv[1], 10, parmv[0]); args->retry = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "max_retry") == 0) { } else if (strcmp(parmv[0], "max_retry") == 0) {
args->max_retry = arg_to_int(parmv[1], 10, parmv[0]); args->max_retry = arg_to_int(parmv[1], 10, parmv[0]);
skipping to change at line 2208 skipping to change at line 2261
} else if (strcmp(parmv[0], "delay_upload") == 0) { } else if (strcmp(parmv[0], "delay_upload") == 0) {
args->delay_upload = arg_to_int(parmv[1], 10, parmv[0]); args->delay_upload = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "gui_optimize") == 0) { } else if (strcmp(parmv[0], "gui_optimize") == 0) {
args->gui_optimize = arg_to_int(parmv[1], 10, parmv[0]); args->gui_optimize = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "minimize_mem") == 0) { } else if (strcmp(parmv[0], "minimize_mem") == 0) {
args->minimize_mem = arg_to_int(parmv[1], 10, parmv[0]); args->minimize_mem = arg_to_int(parmv[1], 10, parmv[0]);
} else if (strcmp(parmv[0], "debug") == 0) { } else if (strcmp(parmv[0], "debug") == 0) {
args->debug |= debug_opts(parmv[1]); args->debug |= debug_opts(parmv[1]);
args->neon_debug |= debug_opts_neon(parmv[1]); args->neon_debug |= debug_opts_neon(parmv[1]);
} else { } else {
error_at_line(EXIT_FAILURE, 0, filename, lineno, ERR_AT_LINE(filename, lineno, _("unknown option"));
_("unknown option"));
} }
} else if (applies && count == 3) { } else if (applies && count == 3) {
if (strcmp(parmv[0], "add_header") == 0) { if (strcmp(parmv[0], "add_header") == 0) {
char *tmp = args->header; char *tmp = args->header;
args->header = ne_concat(parmv[1], ": ", parmv[2], "\r\n", tmp, args->header = ne_concat(parmv[1], ": ", parmv[2], "\r\n", tmp,
NULL); NULL);
if (tmp) if (tmp)
free(tmp); free(tmp);
} else { } else {
error_at_line(EXIT_FAILURE, 0, filename, lineno, ERR_AT_LINE(filename, lineno, _("unknown option"));
_("unknown option"));
} }
} else if (count < 0 || count > 3) { } else if (count < 0 || count > 3) {
error_at_line(EXIT_FAILURE, 0, filename, lineno, ERR_AT_LINE(filename, lineno, _("malformed line"));
_("malformed line"));
} }
length = getline(&line, &n, file); length = getline(&line, &n, file);
lineno++; lineno++;
} }
if (line) if (line)
free(line); free(line);
fclose(file); fclose(file);
} }
skipping to change at line 2302 skipping to change at line 2352
static void static void
read_secrets(dav_args *args, const char *filename) read_secrets(dav_args *args, const char *filename)
{ {
struct stat st; struct stat st;
if (stat(filename, &st) < 0) { if (stat(filename, &st) < 0) {
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_ERR), syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_ERR),
_("opening %s failed"), filename); _("opening %s failed"), filename);
return; return;
} }
if (st.st_uid != geteuid()) if (st.st_uid != geteuid())
error(EXIT_FAILURE, 0, _("file %s has wrong owner"), filename); ERR(_("file %s has wrong owner"), filename);
if ((st.st_mode & if ((st.st_mode &
(S_IXUSR | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX)) != 0) (S_IXUSR | S_IRWXG | S_IRWXO | S_ISUID | S_ISGID | S_ISVTX)) != 0)
error(EXIT_FAILURE, 0, _("file %s has wrong permissions"), filename); ERR(_("file %s has wrong permissions"), filename);
FILE *file = fopen(filename, "r"); FILE *file = fopen(filename, "r");
if (!file) { if (!file) {
syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_ERR), syslog(LOG_MAKEPRI(LOG_DAEMON, LOG_ERR),
_("opening %s failed"), filename); _("opening %s failed"), filename);
return; return;
} }
size_t n = 0; size_t n = 0;
char *line = NULL; char *line = NULL;
int length = getline(&line, &n, file); int length = getline(&line, &n, file);
int lineno = 1; int lineno = 1;
while (length > 0) { while (length > 0) {
int parmc = 3; int parmc = 3;
char *parmv[parmc]; char *parmv[parmc];
int count; int count;
count = parse_line(line, parmc, parmv); count = parse_line(line, parmc, parmv);
if (count != 0 && count != 3 && count != 2) if (count != 0 && count != 3 && count != 2)
error_at_line(EXIT_FAILURE, 0, filename, lineno, ERR_AT_LINE(filename, lineno, _("malformed line"));
_("malformed line"));
if (count == 2 || count == 3) { if (count == 2 || count == 3) {
char *scheme = NULL; char *scheme = NULL;
char *host = NULL; char *host = NULL;
int port = 0; int port = 0;
char *path = 0; char *path = 0;
split_uri(&scheme, &host, &port, &path, parmv[0]); split_uri(&scheme, &host, &port, &path, parmv[0]);
int p_port = port; int p_port = port;
if (scheme && !port) if (scheme && !port)
port = ne_uri_defaultport(scheme); port = ne_uri_defaultport(scheme);
char *mp = canonicalize_file_name(parmv[0]); char *mp = mcanonicalize_file_name(parmv[0]);
char *ccert = NULL; char *ccert = NULL;
if (args->clicert) { if (args->clicert) {
ccert = strrchr(args->clicert, '/'); ccert = strrchr(args->clicert, '/');
if (ccert && *(ccert + 1) == '\0') if (ccert && *(ccert + 1) == '\0')
ccert = NULL; ccert = NULL;
if (ccert) if (ccert)
ccert++; ccert++;
} }
skipping to change at line 2392 skipping to change at line 2441
} }
args->p_user = ne_strdup(parmv[1]); args->p_user = ne_strdup(parmv[1]);
if (count == 3) if (count == 3)
args->p_passwd = ne_strdup(parmv[2]); args->p_passwd = ne_strdup(parmv[2]);
} else if (args->clicert } else if (args->clicert
&& (strcmp(parmv[0], args->clicert) == 0 && (strcmp(parmv[0], args->clicert) == 0
|| strcmp(parmv[0], ccert) == 0)) { || strcmp(parmv[0], ccert) == 0)) {
if (count != 2) if (count != 2)
error_at_line(EXIT_FAILURE, 0, filename, lineno, ERR_AT_LINE(filename, lineno, _("malformed line"));
_("malformed line"));
if (args->clicert_pw) { if (args->clicert_pw) {
memset(args->clicert_pw, '\0', strlen(args->clicert_pw)); memset(args->clicert_pw, '\0', strlen(args->clicert_pw));
free(args->clicert_pw); free(args->clicert_pw);
} }
args->clicert_pw = ne_strdup(parmv[1]); args->clicert_pw = ne_strdup(parmv[1]);
} }
if (scheme) free(scheme); if (scheme) free(scheme);
if (host) free(host); if (host) free(host);
if (path) free(path); if (path) free(path);
 End of changes. 123 change blocks. 
165 lines changed or deleted 214 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)