Mercurial > irccd
changeset 1025:49a126e8aed0
irccd: transport can now set an uid/gid
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 24 Feb 2021 09:38:02 +0100 |
parents | 11b75fdc84de |
children | 724ecacb5a17 |
files | CHANGES.md irccd/conf.y irccd/irccd.conf irccd/lex.l irccd/transport.c irccd/transport.h man/irccd.conf.5 |
diffstat | 7 files changed, 182 insertions(+), 54 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.md Tue Feb 23 20:57:37 2021 +0100 +++ b/CHANGES.md Wed Feb 24 09:38:02 2021 +0100 @@ -15,6 +15,8 @@ - Irccd keeps track of nicknames in channels by capturing join/part/kick and mode changes. It is now more convenient from the plugins to quickly inspect if someone is present on a channel. +- It is now possible to change uid/gid of the transport socket file. The file is + also created with permissions 664. irccdctl --------
--- a/irccd/conf.y Tue Feb 23 20:57:37 2021 +0100 +++ b/irccd/conf.y Wed Feb 24 09:38:02 2021 +0100 @@ -19,7 +19,9 @@ %{ #include <err.h> +#include <grp.h> #include <limits.h> +#include <pwd.h> #include <stdio.h> #include <string.h> #include <stdlib.h> @@ -59,6 +61,11 @@ struct string_list *events; }; +struct transport_params { + uid_t uid; + gid_t gid; +}; + struct server_params { char *hostname; char *password; @@ -124,6 +131,8 @@ %union { int ival; char *sval; + uid_t uid; + gid_t gid; struct pair *pair; struct pair_list *pair_list; @@ -134,6 +143,7 @@ struct server_params *server; struct plugin_params *plugin; struct rule_params *rule; + struct transport_params *tpt; }; %token <ival> T_NUMBER T_LOG_VERBOSITY T_RULE_ACTION @@ -145,6 +155,7 @@ %token T_COMMA %token T_CONFIG %token T_EVENTS +%token T_GID %token T_HOOK %token T_HOSTNAME %token T_IDENT @@ -166,12 +177,17 @@ %token T_TEMPLATES %token T_TO %token T_TRANSPORT +%token T_UID +%token T_WITH %type <ival> log_verbosity %type <sval> plugin_location %type <plugin> plugin_params plugin_params_opt %type <rule> rule_params rule_params_opt %type <server> server_params +%type <uid> transport_params_uid +%type <gid> transport_params_gid +%type <tpt> transport_params %type <pair> pair %type <pair_list> pair_list plugin_templates plugin_config plugin_paths @@ -195,50 +211,6 @@ | hook ; -log_verbosity - : T_LOG_VERBOSITY - { - $$ = $1; - } - | - { - $$ = 0; - } - ; - -logs - : T_LOGS log_verbosity - { - irc_log_set_verbose($2); - } - | T_LOGS log_verbosity T_TO T_LOG_TYPE - { - irc_log_set_verbose($2); - - if (strcmp($4, "console") == 0) - irc_log_to_console(); - else if (strcmp($4, "syslog") == 0) - irc_log_to_syslog(); - else - errx(1, "missing log file path"); - - free($4); - } - | T_LOGS log_verbosity T_TO T_LOG_TYPE T_STRING - { - irc_log_to_file($4); - free($4); - } - ; - -transport - : T_TRANSPORT T_TO T_STRING - { - transport_bind($3); - free($3); - } - ; - string : T_STRING { @@ -283,6 +255,102 @@ } ; +log_verbosity + : T_LOG_VERBOSITY + { + $$ = $1; + } + | + { + $$ = 0; + } + ; + +logs + : T_LOGS log_verbosity + { + irc_log_set_verbose($2); + } + | T_LOGS log_verbosity T_TO T_LOG_TYPE + { + irc_log_set_verbose($2); + + if (strcmp($4, "console") == 0) + irc_log_to_console(); + else if (strcmp($4, "syslog") == 0) + irc_log_to_syslog(); + else + errx(1, "missing log file path"); + + free($4); + } + | T_LOGS log_verbosity T_TO T_LOG_TYPE T_STRING + { + irc_log_to_file($4); + free($4); + } + ; + +transport_params_uid + : T_UID T_NUMBER + { + $$ = (uid_t)$2; + } + | T_UID T_STRING + { + struct passwd *pwd; + + if (!(pwd = getpwnam($2))) + errx(1, "invalid uid: %s", $2); + + free($2); + $$ = pwd->pw_uid; + } + ; + +transport_params_gid + : T_GID T_NUMBER + { + $$ = (gid_t)$2; + } + | T_GID T_STRING + { + struct group *grp; + + if (!(grp = getgrnam($2))) + errx(1, "invalid uid: %s", $2); + + free($2); + $$ = grp->gr_gid; + } + ; + +transport_params + : T_WITH transport_params_uid transport_params_gid + { + $$ = irc_util_malloc(sizeof (*$$)); + $$->uid = $2; + $$->gid = $3; + } + | + { + $$ = NULL; + } + ; + +transport + : T_TRANSPORT T_TO T_STRING transport_params + { + if ($4) + transport_bindp($3, $4->uid, $4->gid); + else + transport_bind($3); + + free($3); + free($4); + } + ; + rule_params : T_SERVERS string_list T_SEMICOLON rule_params {
--- a/irccd/irccd.conf Tue Feb 23 20:57:37 2021 +0100 +++ b/irccd/irccd.conf Wed Feb 24 09:38:02 2021 +0100 @@ -1,7 +1,7 @@ # # This is an example of irccd.conf file. # -# Comments start with a '#' like this header and until the end of lines. +# Comments start with a '#' like this header and until ends at the end of line. # # See the irccd.conf(5) manual page for details of the file syntax and # available options. @@ -19,10 +19,10 @@ logs to console # -# Verbose on syslog +# Verbose on syslog: # logs verbose to syslog # -# Explicitly quiet to a file +# Explicitly quiet to a file: # logs quiet to file "/var/log/irccd/messages" # @@ -33,10 +33,17 @@ # Enable irccd control through a UNIX domain socket via TCP. This is required # for the irccdctl utility. # -# Default is /tmp/irccd.sock +# You must use a quoted string because the parser does not understand a string +# starting with a '/' yet. # -transport to /tmp/irccd.sock +transport to "/tmp/irccd.sock" + +# +# You can use user/group with both names instead of numeric literals. +# transport to "/tmp/irccd.sock" with uid "www" gid "www" +# transport to "/tmp/irccd.sock" with uid 1000 gid "users" +# # # server
--- a/irccd/lex.l Tue Feb 23 20:57:37 2021 +0100 +++ b/irccd/lex.l Wed Feb 24 09:38:02 2021 +0100 @@ -23,6 +23,8 @@ %{ +#include <sys/types.h> + #include <irccd/limits.h> #include <irccd/rule.h> @@ -33,6 +35,7 @@ channels channels config config events events +gid gid hook hook hostname hostname ident ident @@ -56,6 +59,8 @@ templates templates to to transport transport +uid uid +with with brace_open \{ brace_close \} @@ -79,6 +84,7 @@ {comma} return T_COMMA; {config} return T_CONFIG; {events} return T_EVENTS; +{gid} return T_GID; {hook} return T_HOOK; {hostname} return T_HOSTNAME; {ident} return T_IDENT; @@ -98,6 +104,8 @@ {ssl} return T_SSL; {templates} return T_TEMPLATES; {to} return T_TO; +{uid} return T_UID; +{with} return T_WITH; {log_verbosity} { if (strcmp(yytext, "quiet") == 0)
--- a/irccd/transport.c Tue Feb 23 20:57:37 2021 +0100 +++ b/irccd/transport.c Wed Feb 24 09:38:02 2021 +0100 @@ -17,6 +17,7 @@ */ #include <sys/socket.h> +#include <sys/stat.h> #include <sys/types.h> #include <assert.h> #include <errno.h> @@ -39,10 +40,12 @@ static int fd = -1; int -transport_bind(const char *path) +wrap_bind(const char *path, uid_t *uid, gid_t *gid) { assert(path); + int oldumask; + addr.sun_family = PF_LOCAL; if (strlcpy(addr.sun_path, path, sizeof (addr.sun_path)) >= sizeof (addr.sun_path)) { @@ -51,18 +54,30 @@ } /* Silently remove the file first. */ - unlink(addr.sun_path); + unlink(path); if ((fd = socket(PF_LOCAL, SOCK_STREAM, 0)) < 0) goto err; + + /* -ux, -gx, -owx */ + oldumask = umask(S_IXUSR | S_IXGRP | S_IWOTH | S_IXOTH); + if (bind(fd, (const struct sockaddr *)&addr, sizeof (addr)) < 0) goto err; + if (uid && gid && chown(path, *uid, *gid) < 0) + goto err; + + umask(oldumask); + if (listen(fd, 16) < 0) goto err; irc_log_info("transport: listening on %s", path); irc_log_debug("transport: file descriptor %d", fd); + if (uid && gid) + irc_log_info("transport: uid=%d, gid=%d", (int)*uid, (int)*gid); + return 0; err: @@ -76,6 +91,18 @@ return -1; } +int +transport_bind(const char *path) +{ + return wrap_bind(path, NULL, NULL); +} + +int +transport_bindp(const char *path, uid_t uid, gid_t gid) +{ + return wrap_bind(path, &uid, &gid); +} + void transport_prepare(struct pollfd *pfd) {
--- a/irccd/transport.h Tue Feb 23 20:57:37 2021 +0100 +++ b/irccd/transport.h Wed Feb 24 09:38:02 2021 +0100 @@ -19,6 +19,8 @@ #ifndef IRCCD_TRANSPORT_H #define IRCCD_TRANSPORT_H +#include <sys/types.h> + #include "limits.h" struct pollfd; @@ -28,6 +30,9 @@ int transport_bind(const char *); +int +transport_bindp(const char *, uid_t, gid_t); + void transport_prepare(struct pollfd *);
--- a/man/irccd.conf.5 Tue Feb 23 20:57:37 2021 +0100 +++ b/man/irccd.conf.5 Wed Feb 24 09:38:02 2021 +0100 @@ -113,10 +113,18 @@ utility or any networking program that can communicate through a UNIX domain socket. .Pp -.Ar transport to path +.Ar transport to path [with uid value gid value] +.Pp +Create the UNIX domain socket on +.Pa path . .Pp -Enable transport on -.Pa path . +The optional +.Ar uid +and +.Ar gid +keywords can take an optional +.Ar value +to change socket owner and group respectively, it can be a string or a number. .\" server .Ss server This section is used to connect to one or more server. Create a new server @@ -277,6 +285,9 @@ # Logs to syslog instead of console (which is the default). logs verbose to syslog +# Enable transport with default permissions. +transport to "/tmp/irccd.sock" + # # Create a server "example" that connect to example.org using "fr" as nickname, # "francis" as username and "Francis Meyer" as realname.