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 |