If this works everywhere we should be able to manage control socket permissions using just the filesystem
# no permissions for "other" users. These permissions form
# minimal security, and should not be relied on.
#
- socket = ${run_dir}/${name}.sock
+ socket = ${run_dir}/control/${name}.sock
#
# The following two parameters perform authentication and
/* util.c */
#define MEM(x) if (!(x)) { ERROR("%s[%u] OUT OF MEMORY", __FILE__, __LINE__); _fr_exit_now(__FILE__, __LINE__, 1); }
void (*reset_signal(int signo, void (*func)(int)))(int);
-int rad_mkdir(char *directory, mode_t mode);
+int rad_mkdir(char *directory, mode_t mode, uid_t uid, gid_t gid);
size_t rad_filename_escape(UNUSED REQUEST *request, char *out, size_t outlen,
char const *in, UNUSED void *arg);
ssize_t rad_filename_unescape(char *out, size_t outlen, char const *in, size_t inlen);
sock->copy = NULL;
if (sock->path) sock->copy = talloc_typed_strdup(sock, sock->path);
-#if defined(HAVE_GETPEEREID) || defined (SO_PEERCRED)
if (sock->uid_name) {
struct passwd *pwd;
sock->gid = -1;
}
-#else /* can't get uid or gid of connecting user */
-
- if (sock->uid_name || sock->gid_name) {
- ERROR("System does not support uid or gid authentication for sockets");
- return -1;
- }
-
-#endif
-
if (!sock->mode_name) {
sock->co.mode = FR_READ;
} else {
sock->co.mode = fr_str2int(mode_names, sock->mode_name, 0);
if (!sock->co.mode) {
- ERROR("Invalid mode name \"%s\"",
- sock->mode_name);
+ ERROR("Invalid mode name \"%s\"", sock->mode_name);
return -1;
}
}
/*
+ * Ensure the path to the control socket has been created.
+ */
+ {
+ char *dir, *buff;
+ int perm = 0;
+
+ buff = talloc_strdup(cs, sock->path);
+ if (!buff) return -1;
+ dir = dirname(buff);
+
+ if ((sock->uid == (uid_t) -1) && (sock->gid == (gid_t) -1)) {
+ perm = 0770; /* World readable/writable probably dangerous */
+ } else {
+ if (sock->uid != (uid_t) -1) {
+ perm |= 0700;
+ }
+ if (sock->gid != (gid_t) -1) {
+ perm |= 0070;
+ }
+ }
+
+ fr_suid_up();
+ rad_mkdir(dir, perm, sock->uid, sock->gid);
+ fr_suid_down();
+
+ talloc_free(buff);
+ }
+
+ /*
* FIXME: check for absolute pathnames?
* check for uid/gid on the other end...
*/
-
this->fd = fr_server_domain_socket(sock->path);
if (this->fd < 0) {
return -1;
}
-#if defined(HAVE_GETPEEREID) || defined (SO_PEERCRED)
/*
* Don't chown it from (possibly) non-root to root.
* Do chown it from (possibly) root to non-root.
*/
- if ((sock->uid != (uid_t) -1) || (sock->gid != (gid_t) -1)) {
+ if ((sock->uid == (uid_t) -1) && (sock->gid != (gid_t) -1)) {
struct stat buf;
/*
* Don't do chown if it's already owned by us.
*/
if (fstat(this->fd, &buf) < 0) {
- ERROR("Failed reading %s: %s",
- sock->path, fr_syserror(errno));
+ ERROR("Failed reading %s: %s", sock->path, fr_syserror(errno));
return -1;
}
*/
# ifdef __linux__
if ((buf.st_uid != sock->uid) || (buf.st_gid != sock->gid)) {
-
fr_suid_up();
if (fchown(this->fd, sock->uid, sock->gid) < 0) {
ERROR("Failed setting ownership of \"%s\" to (%d, %d): %s",
/*
* We don't want to arbitrarily change directory
* permissions, especially if we don't know we created
- * the directory, so just error out and get the admin
+ * the directory, so just error out and get the user
* to change the permissions.
*/
{
}
# endif
}
-#endif
return 0;
}
if ((dirperm & 0060) != 0) dirperm |= 0010;
if ((dirperm & 0006) != 0) dirperm |= 0001;
- if (rad_mkdir(dir, dirperm) < 0) {
+ if (rad_mkdir(dir, dirperm, -1, -1) < 0) {
fr_strerror_printf("Failed to create directory %s: %s",
dir, strerror(errno));
talloc_free(dir);
p = strrchr(buffer, FR_DIR_SEP);
if (p) {
*p = '\0';
- if (rad_mkdir(buffer, S_IRWXU) < 0) {
+ if (rad_mkdir(buffer, S_IRWXU, -1, -1) < 0) {
ERROR("Failed creating %s: %s", buffer, fr_syserror(errno));
return;
}
* This is so that IF an error is returned, the 'directory' ptr
* points to the name of the file which caused the error.
*/
-int rad_mkdir(char *directory, mode_t mode)
+int rad_mkdir(char *directory, mode_t mode, uid_t uid, gid_t gid)
{
int rcode;
char *p;
if (!p || (p == directory)) return -1;
*p = '\0';
- rcode = rad_mkdir(directory, mode);
+ rcode = rad_mkdir(directory, mode, uid, gid);
if (rcode < 0) return rcode;
/*
/*
* Set the permissions on the created directory.
*/
- return chmod(directory, mode);
+ rcode = chmod(directory, mode);
+ if (rcode < 0) return rcode;
+ if ((uid != (uid_t)-1) || (gid != (gid_t)-1)) rcode = chown(directory, uid, gid);
+ return rcode;
}
/** Escapes the raw string such that it should be safe to use as part of a file path
p = strrchr(path, '/');
if (p) {
*p = '\0';
- if (rad_mkdir(path, 0700) < 0) {
+ if (rad_mkdir(path, 0700, -1, -1) < 0) {
RERROR("rlm_linelog: Failed to create directory %s: %s", path, fr_syserror(errno));
return RLM_MODULE_FAIL;
}
MEM(buff = talloc_typed_strdup(conf, driver->filename));
}
- ret = rad_mkdir(buff, 0700);
+ ret = rad_mkdir(buff, 0700, -1, -1);
talloc_free(buff);
if (ret < 0) {
ERROR("rlm_sql_sqlite: Failed creating directory for SQLite database: %s", fr_syserror(errno));