From 79bb147af7c8d63f8297f4f02cefa8c46628f812 Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Tue, 2 Feb 2021 15:03:05 -0500 Subject: [PATCH] TT#109618 add option to chmod/chown created recordings Change-Id: Ied981b36bc30f6ac24f0c0d6027c008f25029945 --- recording-daemon/.ycm_extra_conf.py | 1 + recording-daemon/main.c | 48 ++++++++++++++++++++++-- recording-daemon/main.h | 4 ++ recording-daemon/output.c | 11 ++++++ recording-daemon/rtpengine-recording.pod | 13 +++++++ 5 files changed, 74 insertions(+), 3 deletions(-) diff --git a/recording-daemon/.ycm_extra_conf.py b/recording-daemon/.ycm_extra_conf.py index a853960a2..d9efec9ac 100644 --- a/recording-daemon/.ycm_extra_conf.py +++ b/recording-daemon/.ycm_extra_conf.py @@ -20,6 +20,7 @@ flags = [ '-I/usr/include/glib-2.0', '-I/usr/lib/x86_64-linux-gnu/glib-2.0/include', '-I/usr/include/mysql', + '-I.', '-I../lib/', '-pthread', '-D_GNU_SOURCE', diff --git a/recording-daemon/main.c b/recording-daemon/main.c index 1e1ed7e13..b4319ddc8 100644 --- a/recording-daemon/main.c +++ b/recording-daemon/main.c @@ -13,12 +13,13 @@ #include #include #include +#include +#include #include "log.h" #include "epoll.h" #include "inotify.h" #include "metafile.h" #include "garbage.h" -#include "loglib.h" #include "auxlib.h" #include "decoder.h" #include "output.h" @@ -38,6 +39,9 @@ static char *output_format = NULL; int output_mixed; int output_single; int output_enabled = 1; +mode_t output_chmod; +uid_t output_chown = -1; +gid_t output_chgrp = -1; int decoding_enabled; char *c_mysql_host, *c_mysql_user, @@ -159,7 +163,10 @@ static void cleanup(void) { static void options(int *argc, char ***argv) { - char *os_str = NULL; + AUTO_CLEANUP_GBUF(os_str); + AUTO_CLEANUP_GBUF(chmod_mode); + AUTO_CLEANUP_GBUF(user_uid); + AUTO_CLEANUP_GBUF(group_gid); GOptionEntry e[] = { { "table", 't', 0, G_OPTION_ARG_INT, &ktable, "Kernel table rtpengine uses", "INT" }, @@ -172,6 +179,9 @@ static void options(int *argc, char ***argv) { { "mp3-bitrate", 0, 0, G_OPTION_ARG_INT, &mp3_bitrate, "Bits per second for MP3 encoding", "INT" }, { "output-mixed", 0, 0, G_OPTION_ARG_NONE, &output_mixed, "Mix participating sources into a single output",NULL }, { "output-single", 0, 0, G_OPTION_ARG_NONE, &output_single, "Create one output file for each source",NULL }, + { "output-chmod", 0, 0, G_OPTION_ARG_STRING, &chmod_mode, "File mode for recordings", "OCTAL" }, + { "output-chown", 0, 0, G_OPTION_ARG_STRING, &user_uid, "File owner for recordings", "USER|UID" }, + { "output-chgrp", 0, 0, G_OPTION_ARG_STRING, &group_gid, "File group for recordings", "GROUP|GID" }, { "mysql-host", 0, 0, G_OPTION_ARG_STRING, &c_mysql_host, "MySQL host for storage of call metadata","HOST|IP" }, { "mysql-port", 0, 0, G_OPTION_ARG_INT, &c_mysql_port, "MySQL port" ,"INT" }, { "mysql-user", 0, 0, G_OPTION_ARG_STRING, &c_mysql_user, "MySQL connection credentials", "USERNAME" }, @@ -229,7 +239,39 @@ static void options(int *argc, char ***argv) { if ((output_storage & OUTPUT_STORAGE_FILE) && !strcmp(output_dir, spool_dir)) die("The spool-dir cannot be the same as the output-dir"); - g_free(os_str); + // no threads here, so safe to use the non-_r versions of these lookups + if (user_uid && *user_uid) { + char *errp; + long uid = strtol(user_uid, &errp, 0); + if (*user_uid && !*errp) + output_chown = uid; + else { + struct passwd *pw = getpwnam(user_uid); + if (!pw) + die("Unknown user name '%s'", user_uid); + output_chown = pw->pw_uid; + } + } + if (group_gid && *group_gid) { + char *errp; + long gid = strtol(group_gid, &errp, 0); + if (*group_gid && !*errp) + output_chgrp = gid; + else { + struct group *gr = getgrnam(group_gid); + if (!gr) + die("Unknown group name '%s'", group_gid); + output_chgrp = gr->gr_gid; + } + } + + if (chmod_mode && *chmod_mode) { + char *errp; + unsigned long m = strtoul(chmod_mode, &errp, 8); + if (*errp || m > 077777) + die("Invalid mode value '%s'", chmod_mode); + output_chmod = m; + } } static void options_free(void) { diff --git a/recording-daemon/main.h b/recording-daemon/main.h index 3f124e429..482ef7ed6 100644 --- a/recording-daemon/main.h +++ b/recording-daemon/main.h @@ -4,6 +4,7 @@ #include "auxlib.h" #include "socket.h" +#include enum output_storage_enum { @@ -20,6 +21,9 @@ extern char *output_dir; extern int output_mixed; extern int output_single; extern int output_enabled; +extern mode_t output_chmod; +extern uid_t output_chown; +extern gid_t output_chgrp; extern int decoding_enabled; extern char *c_mysql_host, *c_mysql_user, diff --git a/recording-daemon/output.c b/recording-daemon/output.c index 6334f1f92..21836fb47 100644 --- a/recording-daemon/output.c +++ b/recording-daemon/output.c @@ -4,8 +4,11 @@ #include #include #include +#include +#include #include "log.h" #include "db.h" +#include "main.h" //static int output_codec_id; @@ -145,6 +148,14 @@ static int output_shutdown(output_t *output) { av_write_trailer(output->fmtctx); avio_closep(&output->fmtctx->pb); ret = 1; + if (output_chmod) + if (chmod(output->filename, output_chmod)) + ilog(LOG_WARN, "Failed to change file mode of '%s%s%s': %s", + FMT_M(output->filename), strerror(errno)); + if (output_chown != -1 || output_chgrp != -1) + if (chown(output->filename, output_chown, output_chgrp)) + ilog(LOG_WARN, "Failed to change file owner/group of '%s%s%s': %s", + FMT_M(output->filename), strerror(errno)); } avformat_free_context(output->fmtctx); diff --git a/recording-daemon/rtpengine-recording.pod b/recording-daemon/rtpengine-recording.pod index 152a6a664..882610ad9 100644 --- a/recording-daemon/rtpengine-recording.pod +++ b/recording-daemon/rtpengine-recording.pod @@ -177,6 +177,19 @@ stream is produced. Audio mixing takes RTP timestamping into account, so gaps and pauses in the RTP media are reflected in the output audio to keep the multiple audio sources in sync. +=item B<--output-chmod=>I + +Change the file permissions of recording files to the given mode. Must be given +as an octal integer, for example B<0660>. + +=item B<--output-chown=>I|I + +=item B<--output-chgrp=>I|I + +Change the ownership of recording files. Either user/group names or numeric IDs +are supported. If the value is blank or given as B<-1> then the user/group is +left unchanged. + =item B<--mysql-host=>I|I =item B<--mysql-port=>I