#include <freeradius-devel/server/virtual_servers.h>
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/perm.h>
#include <freeradius-devel/util/syserror.h>
#include <sys/types.h>
if (!check_perms) {
if (stat(filename, &file->buf) < 0) {
perm_error:
- rad_file_error(errno); /* Write error and euid/egid to error buff */
+ fr_perm_file_error(errno); /* Write error and euid/egid to error buff */
PERROR("Unable to open file \"%s\"", filename);
error:
if (fd >= 0) close(fd);
* @author Alan DeKok (aland@freeradius.org)
* @copyright 2014 The FreeRADIUS server project
*/
+#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
#include <freeradius-devel/server/base.h>
-#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/server/exfile.h>
-#include <freeradius-devel/protocol/freeradius/freeradius.internal.h>
+#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/perm.h>
+#include <freeradius-devel/util/syserror.h>
#include <sys/stat.h>
#include <fcntl.h>
char str_need[10], oct_need[5];
char str_have[10], oct_have[5];
- rad_mode_to_oct(oct_need, permissions);
- rad_mode_to_str(str_need, permissions);
+ fr_perm_mode_to_oct(oct_need, permissions);
+ fr_perm_mode_to_str(str_need, permissions);
- rad_mode_to_oct(oct_have, st.st_mode & ~S_IFMT);
- rad_mode_to_str(str_have, st.st_mode & ~S_IFMT);
+ fr_perm_mode_to_oct(oct_have, st.st_mode & ~S_IFMT);
+ fr_perm_mode_to_str(str_have, st.st_mode & ~S_IFMT);
WARN("File %s permissions are %s (%s) not %s (%s))", filename,
oct_have, str_have, oct_need, str_need);
if (((st.st_mode | permissions) != st.st_mode) &&
(fchmod(ef->entries[i].fd, (st.st_mode & ~S_IFMT) | permissions) < 0)) {
- rad_mode_to_oct(oct_need, (st.st_mode & ~S_IFMT) | permissions);
- rad_mode_to_str(str_need, (st.st_mode & ~S_IFMT) | permissions);
+ fr_perm_mode_to_oct(oct_need, (st.st_mode & ~S_IFMT) | permissions);
+ fr_perm_mode_to_str(str_need, (st.st_mode & ~S_IFMT) | permissions);
WARN("Failed resetting file %s permissions to %s (%s): %s",
filename, oct_need, str_need, fr_syserror(errno));
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/dict.h>
#include <freeradius-devel/util/file.h>
+#include <freeradius-devel/util/perm.h>
#include <freeradius-devel/util/sem.h>
#include <sys/stat.h>
uid_name = cf_pair_value(cf_item_to_pair(ci));
- if (rad_getpwnam(ctx, &user, uid_name) < 0) {
+ if (fr_perm_getpwnam(ctx, &user, uid_name) < 0) {
cf_log_perr(ci, "Cannot get passwd entry for user \"%s\"", uid_name);
return 0;
}
gid_name = cf_pair_value(cf_item_to_pair(ci));
- if (rad_getgrnam(ctx, &group, gid_name) < 0) {
+ if (fr_perm_getgrnam(ctx, &group, gid_name) < 0) {
cf_log_perr(ci, "Cannot resolve group name \"%s\"", gid_name);
return 0;
}
{
struct passwd *user;
- if (rad_getpwuid(config, &user, config->uid) < 0) {
+ if (fr_perm_getpwuid(config, &user, config->uid) < 0) {
fprintf(stderr, "%s: Failed resolving UID %i: %s\n",
config->name, (int)config->uid, fr_syserror(errno));
return -1;
if (setgid(config->server_gid) < 0) {
struct group *group;
- if (rad_getgrgid(config, &group, config->gid) < 0) {
+ if (fr_perm_getgrgid(config, &group, config->gid) < 0) {
fprintf(stderr, "%s: Failed resolving GID %i: %s\n",
config->name, (int)config->gid, fr_syserror(errno));
return -1;
RCSID("$Id$")
-
#include <freeradius-devel/server/base.h>
#include <freeradius-devel/server/stats.h>
#include <freeradius-devel/server/util.h>
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/hex.h>
#include <freeradius-devel/util/misc.h>
+#include <freeradius-devel/util/perm.h>
#include <ctype.h>
#include <fcntl.h>
return argc;
}
-/** Convert mode_t into humanly readable permissions flags
- *
- * @author Jonathan Leffler.
- *
- * @param mode to convert.
- * @param out Where to write the string to, must be exactly 10 bytes long.
- */
-void rad_mode_to_str(char out[static 10], mode_t mode)
-{
- static char const *rwx[] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
-
- strcpy(&out[0], rwx[(mode >> 6) & 0x07]);
- strcpy(&out[3], rwx[(mode >> 3) & 0x07]);
- strcpy(&out[6], rwx[(mode & 7)]);
- if (mode & S_ISUID) out[2] = (mode & 0100) ? 's' : 'S';
- if (mode & S_ISGID) out[5] = (mode & 0010) ? 's' : 'l';
- if (mode & S_ISVTX) out[8] = (mode & 0100) ? 't' : 'T';
- out[9] = '\0';
-}
-
-void rad_mode_to_oct(char out[static 5], mode_t mode)
-{
- out[0] = '0' + ((mode >> 9) & 0x07);
- out[1] = '0' + ((mode >> 6) & 0x07);
- out[2] = '0' + ((mode >> 3) & 0x07);
- out[3] = '0' + (mode & 0x07);
- out[4] = '\0';
-}
-
-/** Resolve a uid to a passwd entry
- *
- * Resolves a uid to a passwd entry. The memory to hold the
- * passwd entry is talloced under ctx, and must be freed when no
- * longer required.
- *
- * @param ctx to allocate passwd entry in.
- * @param out Where to write pointer to entry.
- * @param uid to resolve.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-int rad_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid)
-{
- static size_t len;
- uint8_t *buff;
- int ret;
-
- *out = NULL;
-
- /*
- * We assume this won't change between calls,
- * and that the value is the same, so races don't
- * matter.
- */
- if (len == 0) {
-#ifdef _SC_GETPW_R_SIZE_MAX
- long int sc_len;
-
- sc_len = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (sc_len <= 0) sc_len = 1024;
- len = (size_t)sc_len;
-#else
- len = 1024;
-#endif
- }
-
- buff = talloc_array(ctx, uint8_t, sizeof(struct passwd) + len);
- if (!buff) return -1;
-
- /*
- * In some cases we may need to dynamically
- * grow the string buffer.
- */
- while ((ret = getpwuid_r(uid, (struct passwd *)buff, (char *)(buff + sizeof(struct passwd)),
- talloc_array_length(buff) - sizeof(struct passwd), out)) == ERANGE) {
- MEM(buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2));
- }
-
- if ((ret != 0) || !*out) {
- fr_strerror_printf("%s", (errno != 0) ? fr_syserror(ret) : "Non-existent user");
- talloc_free(buff);
- errno = ret;
- return -1;
- }
-
- talloc_set_type(buff, struct passwd);
- *out = (struct passwd *)buff;
-
- return 0;
-}
-
-/** Resolve a username to a passwd entry
- *
- * Resolves a username to a passwd entry. The memory to hold the
- * passwd entry is talloced under ctx, and must be freed when no
- * longer required.
- *
- * @param ctx to allocate passwd entry in.
- * @param out Where to write pointer to entry.
- * @param name to resolve.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-int rad_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name)
-{
- static size_t len;
- uint8_t *buff;
- int ret;
-
- *out = NULL;
-
- /*
- * We assume this won't change between calls,
- * and that the value is the same, so races don't
- * matter.
- */
- if (len == 0) {
-#ifdef _SC_GETPW_R_SIZE_MAX
- long int sc_len;
-
- sc_len = sysconf(_SC_GETPW_R_SIZE_MAX);
- if (sc_len <= 0) sc_len = 1024;
- len = (size_t)sc_len;
-#else
- sc_len = 1024;
-#endif
- }
-
- buff = talloc_array(ctx, uint8_t, sizeof(struct passwd) + len);
- if (!buff) return -1;
-
- /*
- * In some cases we may need to dynamically
- * grow the string buffer.
- */
- while ((ret = getpwnam_r(name, (struct passwd *)buff, (char *)(buff + sizeof(struct passwd)),
- talloc_array_length(buff) - sizeof(struct passwd), out)) == ERANGE) {
- MEM(buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2));
- }
-
- if ((ret != 0) || !*out) {
- fr_strerror_printf("%s", (errno != 0) ? fr_syserror(ret) : "Non-existent user");
- talloc_free(buff);
- errno = ret;
- return -1;
- }
-
- talloc_set_type(buff, struct passwd);
- *out = (struct passwd *)buff;
-
- return 0;
-}
-
-/** Resolve a gid to a group database entry
- *
- * Resolves a gid to a group database entry. The memory to hold the
- * group entry is talloced under ctx, and must be freed when no
- * longer required.
- *
- * @param ctx to allocate passwd entry in.
- * @param out Where to write pointer to entry.
- * @param gid to resolve.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-int rad_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid)
-{
- static size_t len;
- uint8_t *buff;
- int ret;
-
- *out = NULL;
-
- /*
- * We assume this won't change between calls,
- * and that the value is the same, so races don't
- * matter.
- */
- if (len == 0) {
-#ifdef _SC_GETGR_R_SIZE_MAX
- long int sc_len;
-
- sc_len = sysconf(_SC_GETGR_R_SIZE_MAX);
- if (sc_len <= 0) sc_len = 1024;
- len = (size_t)sc_len;
-#else
- sc_len = 1024;
-#endif
- }
-
- buff = talloc_array(ctx, uint8_t, sizeof(struct group) + len);
- if (!buff) return -1;
-
- /*
- * In some cases we may need to dynamically
- * grow the string buffer.
- */
- while ((ret = getgrgid_r(gid, (struct group *)buff, (char *)(buff + sizeof(struct group)),
- talloc_array_length(buff) - sizeof(struct group), out)) == ERANGE) {
- MEM(buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2));
- }
-
- if ((ret != 0) || !*out) {
- fr_strerror_printf("%s", (ret != 0) ? fr_syserror(ret) : "Non-existent group");
- talloc_free(buff);
- errno = ret;
- return -1;
- }
-
- talloc_set_type(buff, struct group);
- *out = (struct group *)buff;
-
- return 0;
-}
-
-/** Resolve a group name to a group database entry
- *
- * Resolves a group name to a group database entry.
- * The memory to hold the group entry is talloced under ctx,
- * and must be freed when no longer required.
- *
- * @param ctx to allocate passwd entry in.
- * @param out Where to write pointer to entry.
- * @param name to resolve.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-int rad_getgrnam(TALLOC_CTX *ctx, struct group **out, char const *name)
-{
- static size_t len;
- uint8_t *buff;
- int ret;
-
- *out = NULL;
-
- /*
- * We assume this won't change between calls,
- * and that the value is the same, so races don't
- * matter.
- */
- if (len == 0) {
-#ifdef _SC_GETGR_R_SIZE_MAX
- long int sc_len;
-
- sc_len = sysconf(_SC_GETGR_R_SIZE_MAX);
- if (sc_len <= 0) sc_len = 1024;
- len = (size_t)sc_len;
-#else
- len = 1024;
-#endif
- }
-
- buff = talloc_array(ctx, uint8_t, sizeof(struct group) + len);
- if (!buff) return -1;
-
- /*
- * In some cases we may need to dynamically
- * grow the string buffer.
- */
- while ((ret = getgrnam_r(name, (struct group *)buff, (char *)(buff + sizeof(struct group)),
- talloc_array_length(buff) - sizeof(struct group), out)) == ERANGE) {
- MEM(buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2));
- }
-
- if ((ret != 0) || !*out) {
- fr_strerror_printf("%s", (ret != 0) ? fr_syserror(ret) : "Non-existent group");
- talloc_free(buff);
- errno = ret;
- return -1;
- }
-
- talloc_set_type(buff, struct group);
- *out = (struct group *)buff;
-
- return 0;
-}
-
-/** Resolve a group name to a GID
- *
- * @param ctx TALLOC_CTX for temporary allocations.
- * @param name of group.
- * @param out where to write gid.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-int rad_getgid(TALLOC_CTX *ctx, gid_t *out, char const *name)
-{
- int ret;
- struct group *result;
-
- ret = rad_getgrnam(ctx, &result, name);
- if (ret < 0) return -1;
-
- *out = result->gr_gid;
- talloc_free(result);
- return 0;
-}
-
-/** Print uid to a string
- *
- * @param ctx TALLOC_CTX for temporary allocations.
- * @param uid to resolve.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-char *rad_asprint_uid(TALLOC_CTX *ctx, uid_t uid)
-{
- struct passwd *result;
- char *out;
-
- if (rad_getpwuid(ctx, &result, uid) < 0) return NULL;
- out = talloc_typed_strdup(ctx, result->pw_name);
- talloc_free(result);
-
- return out;
-}
-
-/** Print gid to a string
- *
- * @param ctx TALLOC_CTX for temporary allocations.
- * @param gid to resolve.
- * @return
- * - 0 on success.
- * - -1 on failure.
- */
-char *rad_asprint_gid(TALLOC_CTX *ctx, uid_t gid){
- struct group *result;
- char *out;
-
- if (rad_getgrgid(ctx, &result, gid) < 0) return NULL;
- out = talloc_typed_strdup(ctx, result->gr_name);
- talloc_free(result);
-
- return out;
-}
-
-/** Write a file access error to the fr_strerror buffer, including euid/egid
- *
- * @note retrieve error with fr_strerror()
- *
- * @param num Usually errno, unless the error is returned by the function.
- */
-void rad_file_error(int num)
-{
- char const *error;
- struct passwd *user = NULL;
- struct group *group = NULL;
-
- error = fr_syserror(num);
-
- if (rad_getpwuid(NULL, &user, geteuid()) < 0) goto finish;
- if (rad_getgrgid(NULL, &group, getegid()) < 0) goto finish;
-
- fr_strerror_printf("Effective user/group - %s:%s: %s", user->pw_name, group->gr_name, error);
-finish:
- talloc_free(user);
- talloc_free(group);
-}
-
#ifdef HAVE_SETUID
static bool doing_setuid = false;
static uid_t suid_down_uid = (uid_t)-1;
struct passwd *passwd;
char const *name;
- name = (rad_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown" : passwd->pw_name;
+ name = (fr_perm_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown" : passwd->pw_name;
ERROR("Failed switching to uid %s: %s", name, fr_syserror(errno));
talloc_free(passwd);
fr_exit_now(EXIT_FAILURE);
struct passwd *passwd;
char const *name;
- name = (rad_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown" : passwd->pw_name;
+ name = (fr_perm_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown" : passwd->pw_name;
ERROR("Failed in permanent switch to uid %s: %s", name, fr_syserror(errno));
talloc_free(passwd);
fr_exit_now(EXIT_FAILURE);
struct passwd *passwd;
char const *name;
- name = (rad_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown": passwd->pw_name;
+ name = (fr_perm_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown": passwd->pw_name;
ERROR("Failed switching to euid %s: %s", name, fr_syserror(errno));
talloc_free(passwd);
fr_exit_now(EXIT_FAILURE);
struct passwd *passwd;
char const *name;
- name = (rad_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown": passwd->pw_name;
+ name = (fr_perm_getpwuid(NULL, &passwd, suid_down_uid) < 0) ? "unknown": passwd->pw_name;
ERROR("Failed switching permanently to uid %s: %s", name, fr_syserror(errno));
talloc_free(passwd);
fr_exit_now(EXIT_FAILURE);
int rad_seuid(uid_t uid)
{
if (seteuid(uid) < 0) {
- int sete_errno = errno; /* errno sets overwritten by rad_getpwuid */
+ int sete_errno = errno; /* errno sets overwritten by fr_perm_getpwuid */
struct passwd *passwd;
- if (rad_getpwuid(NULL, &passwd, uid) < 0) return -1;
+ if (fr_perm_getpwuid(NULL, &passwd, uid) < 0) return -1;
fr_strerror_printf("%s", fr_syserror(sete_errno));
talloc_free(passwd);
int rad_segid(gid_t gid)
{
if (setegid(gid) < 0) {
- int sete_errno = errno; /* errno sets overwritten by rad_getgrgid */
+ int sete_errno = errno; /* errno sets overwritten by fr_perm_getgrgid */
struct group *group;
- if (rad_getgrgid(NULL, &group, gid) < 0) return -1;
+ if (fr_perm_getgrgid(NULL, &group, gid) < 0) return -1;
fr_strerror_printf("%s", fr_syserror(sete_errno));
talloc_free(group);
int max_argc, char const *argv[], bool can_fail,
size_t argv_buflen, char *argv_buf);
-void rad_mode_to_str(char out[static 10], mode_t mode);
-void rad_mode_to_oct(char out[static 5], mode_t mode);
-int rad_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid);
-int rad_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name);
-int rad_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid);
-int rad_getgrnam(TALLOC_CTX *ctx, struct group **out, char const *name);
-int rad_getgid(TALLOC_CTX *ctx, gid_t *out, char const *name);
-char *rad_asprint_uid(TALLOC_CTX *ctx, uid_t uid);
-char *rad_asprint_gid(TALLOC_CTX *ctx, gid_t gid);
-void rad_file_error(int num);
int rad_seuid(uid_t uid);
int rad_segid(gid_t gid);
pair_tokenize.c \
paths.c \
pcap.c \
+ perm.c \
print.c \
proto.c \
rand.c \
--- /dev/null
+/*
+ * This program is is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/** Implementation of filed semaphores that release on exit
+ *
+ * @file src/lib/util/perm.c
+ *
+ * @copyright 2021 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
+ */
+RCSID("$Id$")
+
+#include <freeradius-devel/util/perm.h>
+#include <freeradius-devel/util/strerror.h>
+#include <freeradius-devel/util/syserror.h>
+
+/** Convert mode_t into humanly readable permissions flags
+ *
+ * @author Jonathan Leffler.
+ *
+ * @param mode to convert.
+ * @param out Where to write the string to, must be exactly 10 bytes long.
+ */
+void fr_perm_mode_to_str(char out[static 10], mode_t mode)
+{
+ static char const *rwx[] = {"---", "--x", "-w-", "-wx", "r--", "r-x", "rw-", "rwx"};
+
+ strcpy(&out[0], rwx[(mode >> 6) & 0x07]);
+ strcpy(&out[3], rwx[(mode >> 3) & 0x07]);
+ strcpy(&out[6], rwx[(mode & 7)]);
+ if (mode & S_ISUID) out[2] = (mode & 0100) ? 's' : 'S';
+ if (mode & S_ISGID) out[5] = (mode & 0010) ? 's' : 'l';
+ if (mode & S_ISVTX) out[8] = (mode & 0100) ? 't' : 'T';
+ out[9] = '\0';
+}
+
+void fr_perm_mode_to_oct(char out[static 5], mode_t mode)
+{
+ out[0] = '0' + ((mode >> 9) & 0x07);
+ out[1] = '0' + ((mode >> 6) & 0x07);
+ out[2] = '0' + ((mode >> 3) & 0x07);
+ out[3] = '0' + (mode & 0x07);
+ out[4] = '\0';
+}
+
+/** Resolve a uid to a passwd entry
+ *
+ * Resolves a uid to a passwd entry. The memory to hold the
+ * passwd entry is talloced under ctx, and must be freed when no
+ * longer required.
+ *
+ * @param ctx to allocate passwd entry in.
+ * @param out Where to write pointer to entry.
+ * @param uid to resolve.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+int fr_perm_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid)
+{
+ static size_t len;
+ uint8_t *buff;
+ int ret;
+
+ *out = NULL;
+
+ /*
+ * We assume this won't change between calls,
+ * and that the value is the same, so races don't
+ * matter.
+ */
+ if (len == 0) {
+#ifdef _SC_GETPW_R_SIZE_MAX
+ long int sc_len;
+
+ sc_len = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (sc_len <= 0) sc_len = 1024;
+ len = (size_t)sc_len;
+#else
+ len = 1024;
+#endif
+ }
+
+ buff = talloc_array(ctx, uint8_t, sizeof(struct passwd) + len);
+ if (!buff) return -1;
+
+ /*
+ * In some cases we may need to dynamically
+ * grow the string buffer.
+ */
+ while ((ret = getpwuid_r(uid, (struct passwd *)buff, (char *)(buff + sizeof(struct passwd)),
+ talloc_array_length(buff) - sizeof(struct passwd), out)) == ERANGE) {
+ buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2);
+ }
+
+ if ((ret != 0) || !*out) {
+ fr_strerror_printf("%s", (errno != 0) ? fr_syserror(ret) : "Non-existent user");
+ talloc_free(buff);
+ errno = ret;
+ return -1;
+ }
+
+ talloc_set_type(buff, struct passwd);
+ *out = (struct passwd *)buff;
+
+ return 0;
+}
+
+/** Resolve a username to a passwd entry
+ *
+ * Resolves a username to a passwd entry. The memory to hold the
+ * passwd entry is talloced under ctx, and must be freed when no
+ * longer required.
+ *
+ * @param ctx to allocate passwd entry in.
+ * @param out Where to write pointer to entry.
+ * @param name to resolve.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+int fr_perm_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name)
+{
+ static size_t len;
+ uint8_t *buff;
+ int ret;
+
+ *out = NULL;
+
+ /*
+ * We assume this won't change between calls,
+ * and that the value is the same, so races don't
+ * matter.
+ */
+ if (len == 0) {
+#ifdef _SC_GETPW_R_SIZE_MAX
+ long int sc_len;
+
+ sc_len = sysconf(_SC_GETPW_R_SIZE_MAX);
+ if (sc_len <= 0) sc_len = 1024;
+ len = (size_t)sc_len;
+#else
+ sc_len = 1024;
+#endif
+ }
+
+ buff = talloc_array(ctx, uint8_t, sizeof(struct passwd) + len);
+ if (!buff) return -1;
+
+ /*
+ * In some cases we may need to dynamically
+ * grow the string buffer.
+ */
+ while ((ret = getpwnam_r(name, (struct passwd *)buff, (char *)(buff + sizeof(struct passwd)),
+ talloc_array_length(buff) - sizeof(struct passwd), out)) == ERANGE) {
+ buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2);
+ }
+
+ if ((ret != 0) || !*out) {
+ fr_strerror_printf("%s", (errno != 0) ? fr_syserror(ret) : "Non-existent user");
+ talloc_free(buff);
+ errno = ret;
+ return -1;
+ }
+
+ talloc_set_type(buff, struct passwd);
+ *out = (struct passwd *)buff;
+
+ return 0;
+}
+
+/** Resolve a gid to a group database entry
+ *
+ * Resolves a gid to a group database entry. The memory to hold the
+ * group entry is talloced under ctx, and must be freed when no
+ * longer required.
+ *
+ * @param ctx to allocate passwd entry in.
+ * @param out Where to write pointer to entry.
+ * @param gid to resolve.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+int fr_perm_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid)
+{
+ static size_t len;
+ uint8_t *buff;
+ int ret;
+
+ *out = NULL;
+
+ /*
+ * We assume this won't change between calls,
+ * and that the value is the same, so races don't
+ * matter.
+ */
+ if (len == 0) {
+#ifdef _SC_GETGR_R_SIZE_MAX
+ long int sc_len;
+
+ sc_len = sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (sc_len <= 0) sc_len = 1024;
+ len = (size_t)sc_len;
+#else
+ sc_len = 1024;
+#endif
+ }
+
+ buff = talloc_array(ctx, uint8_t, sizeof(struct group) + len);
+ if (!buff) return -1;
+
+ /*
+ * In some cases we may need to dynamically
+ * grow the string buffer.
+ */
+ while ((ret = getgrgid_r(gid, (struct group *)buff, (char *)(buff + sizeof(struct group)),
+ talloc_array_length(buff) - sizeof(struct group), out)) == ERANGE) {
+ buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2);
+ }
+
+ if ((ret != 0) || !*out) {
+ fr_strerror_printf("%s", (ret != 0) ? fr_syserror(ret) : "Non-existent group");
+ talloc_free(buff);
+ errno = ret;
+ return -1;
+ }
+
+ talloc_set_type(buff, struct group);
+ *out = (struct group *)buff;
+
+ return 0;
+}
+
+/** Resolve a group name to a group database entry
+ *
+ * Resolves a group name to a group database entry.
+ * The memory to hold the group entry is talloced under ctx,
+ * and must be freed when no longer required.
+ *
+ * @param ctx to allocate passwd entry in.
+ * @param out Where to write pointer to entry.
+ * @param name to resolve.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+int fr_perm_getgrnam(TALLOC_CTX *ctx, struct group **out, char const *name)
+{
+ static size_t len;
+ uint8_t *buff;
+ int ret;
+
+ *out = NULL;
+
+ /*
+ * We assume this won't change between calls,
+ * and that the value is the same, so races don't
+ * matter.
+ */
+ if (len == 0) {
+#ifdef _SC_GETGR_R_SIZE_MAX
+ long int sc_len;
+
+ sc_len = sysconf(_SC_GETGR_R_SIZE_MAX);
+ if (sc_len <= 0) sc_len = 1024;
+ len = (size_t)sc_len;
+#else
+ len = 1024;
+#endif
+ }
+
+ buff = talloc_array(ctx, uint8_t, sizeof(struct group) + len);
+ if (!buff) return -1;
+
+ /*
+ * In some cases we may need to dynamically
+ * grow the string buffer.
+ */
+ while ((ret = getgrnam_r(name, (struct group *)buff, (char *)(buff + sizeof(struct group)),
+ talloc_array_length(buff) - sizeof(struct group), out)) == ERANGE) {
+ buff = talloc_realloc_size(ctx, buff, talloc_array_length(buff) * 2);
+ }
+
+ if ((ret != 0) || !*out) {
+ fr_strerror_printf("%s", (ret != 0) ? fr_syserror(ret) : "Non-existent group");
+ talloc_free(buff);
+ errno = ret;
+ return -1;
+ }
+
+ talloc_set_type(buff, struct group);
+ *out = (struct group *)buff;
+
+ return 0;
+}
+
+/** Resolve a group name to a GID
+ *
+ * @param ctx TALLOC_CTX for temporary allocations.
+ * @param name of group.
+ * @param out where to write gid.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name)
+{
+ int ret;
+ struct group *result;
+
+ ret = fr_perm_getgrnam(ctx, &result, name);
+ if (ret < 0) return -1;
+
+ *out = result->gr_gid;
+ talloc_free(result);
+ return 0;
+}
+
+/** Print uid to a string
+ *
+ * @param ctx TALLOC_CTX for temporary allocations.
+ * @param uid to resolve.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+char *fr_perm_uid_to_str(TALLOC_CTX *ctx, uid_t uid)
+{
+ struct passwd *result;
+ char *out;
+
+ if (fr_perm_getpwuid(ctx, &result, uid) < 0) return NULL;
+ out = talloc_typed_strdup(ctx, result->pw_name);
+ talloc_free(result);
+
+ return out;
+}
+
+/** Print gid to a string
+ *
+ * @param ctx TALLOC_CTX for temporary allocations.
+ * @param gid to resolve.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+char *fr_perm_gid_to_str(TALLOC_CTX *ctx, uid_t gid){
+ struct group *result;
+ char *out;
+
+ if (fr_perm_getgrgid(ctx, &result, gid) < 0) return NULL;
+ out = talloc_typed_strdup(ctx, result->gr_name);
+ talloc_free(result);
+
+ return out;
+}
+
+/** Write a file access error to the fr_strerror buffer, including euid/egid
+ *
+ * @note retrieve error with fr_strerror()
+ *
+ * @param num Usually errno, unless the error is returned by the function.
+ */
+void fr_perm_file_error(int num)
+{
+ char const *error;
+ struct passwd *user = NULL;
+ struct group *group = NULL;
+
+ error = fr_syserror(num);
+
+ if (fr_perm_getpwuid(NULL, &user, geteuid()) < 0) goto finish;
+ if (fr_perm_getgrgid(NULL, &group, getegid()) < 0) goto finish;
+
+ fr_strerror_printf("Effective user/group - %s:%s: %s", user->pw_name, group->gr_name, error);
+finish:
+ talloc_free(user);
+ talloc_free(group);
+}
--- /dev/null
+#pragma once
+/*
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/** Functions to produce and parse the FreeRADIUS presentation format
+ *
+ * @file src/lib/util/perm.h
+ *
+ * @copyright 2021 Arran Cudbard-Bell (a.cudbardb@freeradius.org)
+ */
+RCSIDH(perm_h, "$Id$")
+
+#include <pwd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <grp.h>
+
+#include <freeradius-devel/util/talloc.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void fr_perm_mode_to_str(char out[static 10], mode_t mode);
+void fr_perm_mode_to_oct(char out[static 5], mode_t mode);
+int fr_perm_getpwuid(TALLOC_CTX *ctx, struct passwd **out, uid_t uid);
+int fr_perm_getpwnam(TALLOC_CTX *ctx, struct passwd **out, char const *name);
+int fr_perm_getgrgid(TALLOC_CTX *ctx, struct group **out, gid_t gid);
+int fr_perm_getgrnam(TALLOC_CTX *ctx, struct group **out, char const *name);
+int fr_perm_gid_from_str(TALLOC_CTX *ctx, gid_t *out, char const *name);
+char *fr_perm_uid_to_str(TALLOC_CTX *ctx, uid_t uid);
+char *fr_perm_gid_to_str(TALLOC_CTX *ctx, gid_t gid);
+void fr_perm_file_error(int num);
+
+#ifdef __cplusplus
+}
+#endif
#include <freeradius-devel/server/protocol.h>
#include <freeradius-devel/util/debug.h>
#include <freeradius-devel/util/fopencookie.h>
+#include <freeradius-devel/util/perm.h>
#include <freeradius-devel/util/socket.h>
#include <freeradius-devel/util/trie.h>
#include <netdb.h>
struct passwd *user;
struct group *group;
- if (rad_getpwuid(NULL, &user, euid) < 0) goto error;
- if (rad_getgrgid(NULL, &group, egid) < 0) {
+ if (fr_perm_getpwuid(NULL, &user, euid) < 0) goto error;
+ if (fr_perm_getgrgid(NULL, &group, egid) < 0) {
talloc_free(user);
goto error;
}
if ((uid != (uid_t)-1) && (st.st_uid != uid)) {
struct passwd *need_user, *have_user;
- if (rad_getpwuid(NULL, &need_user, uid) < 0) goto error;
- if (rad_getpwuid(NULL, &have_user, st.st_uid) < 0) {
+ if (fr_perm_getpwuid(NULL, &need_user, uid) < 0) goto error;
+ if (fr_perm_getpwuid(NULL, &have_user, st.st_uid) < 0) {
talloc_free(need_user);
goto error;
}
if ((gid != (gid_t)-1) && (st.st_gid != gid)) {
struct group *need_group, *have_group;
- if (rad_getgrgid(NULL, &need_group, gid) < 0) goto error;
- if (rad_getgrgid(NULL, &have_group, st.st_gid) < 0) {
+ if (fr_perm_getgrgid(NULL, &need_group, gid) < 0) goto error;
+ if (fr_perm_getgrgid(NULL, &have_group, st.st_gid) < 0) {
talloc_free(need_group);
goto error;
}
char str_need[10], oct_need[5];
char str_have[10], oct_have[5];
- rad_mode_to_str(str_need, perm);
- rad_mode_to_oct(oct_need, perm);
- rad_mode_to_str(str_have, st.st_mode);
- rad_mode_to_oct(oct_have, st.st_mode);
+ fr_perm_mode_to_str(str_need, perm);
+ fr_perm_mode_to_oct(oct_need, perm);
+ fr_perm_mode_to_str(str_have, st.st_mode);
+ fr_perm_mode_to_oct(oct_have, st.st_mode);
fr_strerror_printf("Control socket directory must have permissions %s (%s), current "
"permissions are %s (%s)", str_need, oct_need, str_have, oct_have);
goto error;
if (fchmod(sock_fd, perm) < 0) {
char str_need[10], oct_need[5];
- rad_mode_to_str(str_need, perm);
- rad_mode_to_oct(oct_need, perm);
+ fr_perm_mode_to_str(str_need, perm);
+ fr_perm_mode_to_oct(oct_need, perm);
fr_strerror_printf("Failed changing socket permissions to %s (%s)", str_need, oct_need);
goto sock_error;
struct passwd *user;
struct group *group;
- if (rad_getpwuid(NULL, &user, uid) < 0) goto sock_error;
- if (rad_getgrgid(NULL, &group, gid) < 0) {
+ if (fr_perm_getpwuid(NULL, &user, uid) < 0) goto sock_error;
+ if (fr_perm_getgrgid(NULL, &group, gid) < 0) {
talloc_free(user);
goto sock_error;
}
if (inst->uid_name) {
struct passwd *pwd;
- if (rad_getpwnam(cs, &pwd, inst->uid_name) < 0) {
+ if (fr_perm_getpwnam(cs, &pwd, inst->uid_name) < 0) {
PERROR("Failed getting uid for %s", inst->uid_name);
return -1;
}
}
if (inst->gid_name) {
- if (rad_getgid(cs, &inst->gid, inst->gid_name) < 0) {
+ if (fr_perm_gid_from_str(cs, &inst->gid, inst->gid_name) < 0) {
PERROR("Failed getting gid for %s", inst->gid_name);
return -1;
}
#define LOG_PREFIX_ARGS inst->name
#include <freeradius-devel/server/base.h>
+#include <freeradius-devel/server/exfile.h>
#include <freeradius-devel/server/module.h>
#include <freeradius-devel/util/debug.h>
-#include <freeradius-devel/server/exfile.h>
+#include <freeradius-devel/util/perm.h>
#include <ctype.h>
#include <fcntl.h>
if (inst->group != NULL) {
gid = strtol(inst->group, &endptr, 10);
if (*endptr != '\0') {
- if (rad_getgid(request, &gid, inst->group) < 0) {
+ if (fr_perm_gid_from_str(request, &gid, inst->group) < 0) {
RDEBUG2("Unable to find system group '%s'", inst->group);
goto skip_group;
}
RCSID("$Id$")
#include <freeradius-devel/server/base.h>
+#include <freeradius-devel/server/exfile.h>
#include <freeradius-devel/server/module.h>
#include <freeradius-devel/util/debug.h>
-#include <freeradius-devel/server/exfile.h>
+#include <freeradius-devel/util/perm.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
inst->file.group = strtol(inst->file.group_str, &endptr, 10);
if (*endptr != '\0') {
- if (rad_getgid(inst, &(inst->file.group), inst->file.group_str) < 0) {
+ if (fr_perm_gid_from_str(inst, &(inst->file.group), inst->file.group_str) < 0) {
cf_log_err(conf, "Unable to find system group \"%s\"",
inst->file.group_str);
return -1;
#include <freeradius-devel/server/base.h>
#include <freeradius-devel/server/module.h>
#include <freeradius-devel/util/debug.h>
+#include <freeradius-devel/util/perm.h>
#include <ctype.h>
#include <stdlib.h>
/* resolve SACL */
uuid_clear(guid_sacl);
- if (rad_getgid(request, &gid, kRadiusSACLName) < 0) {
+ if (fr_perm_gid_from_str(request, &gid, kRadiusSACLName) < 0) {
RDEBUG2("The SACL group \"%s\" does not exist on this system", kRadiusSACLName);
} else {
err = mbr_gid_to_uuid(gid, guid_sacl);
/* resolve user */
uuid_clear(uuid);
- rad_getpwnam(request, &userdata, username->vp_strvalue);
+ fr_perm_getpwnam(request, &userdata, username->vp_strvalue);
if (userdata != NULL) {
err = mbr_uid_to_uuid(userdata->pw_uid, uuid);
if (err != 0)
#define LOG_PREFIX "rlm_unix (%s) - "
#define LOG_PREFIX_ARGS inst->name
+#include <freeradius-devel/radius/radius.h>
#include <freeradius-devel/server/base.h>
#include <freeradius-devel/server/module.h>
#include <freeradius-devel/server/sysutmp.h>
-#include <freeradius-devel/radius/radius.h>
+#include <freeradius-devel/util/perm.h>
#include <grp.h>
#include <pwd.h>
username = fr_pair_find_by_da(&request->request_pairs, attr_user_name, 0);
if (!username) return -1;
- if (rad_getpwnam(request, &pwd, username->vp_strvalue) < 0) {
+ if (fr_perm_getpwnam(request, &pwd, username->vp_strvalue) < 0) {
RPEDEBUG("Failed resolving user name");
return -1;
}
- if (rad_getgrnam(request, &grp, check->vp_strvalue) < 0) {
+ if (fr_perm_getgrnam(request, &grp, check->vp_strvalue) < 0) {
RPEDEBUG("Failed resolving group name");
talloc_free(pwd);
return -1;