blob: b1631c90135ae1734b7bf8f0f347fb051e241505 [file] [log] [blame]
Willy Tarreau13180342020-08-28 11:54:59 +02001/*
2 * Configuration parsing for UNIX sockets (bind and server keywords)
3 *
4 * Copyright 2000-2020 Willy Tarreau <w@1wt.eu>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
13#include <ctype.h>
14#include <errno.h>
15#include <fcntl.h>
16#include <grp.h>
17#include <pwd.h>
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21#include <time.h>
22
23#include <sys/param.h>
24#include <sys/socket.h>
25#include <sys/types.h>
26#include <sys/un.h>
27
28#include <netinet/tcp.h>
29#include <netinet/in.h>
30
31#include <haproxy/api.h>
32#include <haproxy/arg.h>
33#include <haproxy/errors.h>
34#include <haproxy/list.h>
35#include <haproxy/listener.h>
36#include <haproxy/namespace.h>
37#include <haproxy/proxy-t.h>
38#include <haproxy/server.h>
39#include <haproxy/tools.h>
40
41/* parse the "mode" bind keyword */
42static int bind_parse_mode(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
43{
44 char *endptr;
45
46 conf->ux.mode = strtol(args[cur_arg + 1], &endptr, 8);
47
48 if (!*args[cur_arg + 1] || *endptr) {
49 memprintf(err, "'%s' : missing or invalid mode '%s' (octal integer expected)", args[cur_arg], args[cur_arg + 1]);
50 return ERR_ALERT | ERR_FATAL;
51 }
52
53 return 0;
54}
55
56/* parse the "gid" bind keyword */
57static int bind_parse_gid(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
58{
59 if (!*args[cur_arg + 1]) {
60 memprintf(err, "'%s' : missing value", args[cur_arg]);
61 return ERR_ALERT | ERR_FATAL;
62 }
63
64 conf->ux.gid = atol(args[cur_arg + 1]);
65 return 0;
66}
67
68/* parse the "group" bind keyword */
69static int bind_parse_group(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
70{
71 struct group *group;
72
73 if (!*args[cur_arg + 1]) {
74 memprintf(err, "'%s' : missing group name", args[cur_arg]);
75 return ERR_ALERT | ERR_FATAL;
76 }
77
78 group = getgrnam(args[cur_arg + 1]);
79 if (!group) {
80 memprintf(err, "'%s' : unknown group name '%s'", args[cur_arg], args[cur_arg + 1]);
81 return ERR_ALERT | ERR_FATAL;
82 }
83
84 conf->ux.gid = group->gr_gid;
85 return 0;
86}
87
88/* parse the "uid" bind keyword */
89static int bind_parse_uid(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
90{
91 if (!*args[cur_arg + 1]) {
92 memprintf(err, "'%s' : missing value", args[cur_arg]);
93 return ERR_ALERT | ERR_FATAL;
94 }
95
96 conf->ux.uid = atol(args[cur_arg + 1]);
97 return 0;
98}
99
100/* parse the "user" bind keyword */
101static int bind_parse_user(char **args, int cur_arg, struct proxy *px, struct bind_conf *conf, char **err)
102{
103 struct passwd *user;
104
105 if (!*args[cur_arg + 1]) {
106 memprintf(err, "'%s' : missing user name", args[cur_arg]);
107 return ERR_ALERT | ERR_FATAL;
108 }
109
110 user = getpwnam(args[cur_arg + 1]);
111 if (!user) {
112 memprintf(err, "'%s' : unknown user name '%s'", args[cur_arg], args[cur_arg + 1]);
113 return ERR_ALERT | ERR_FATAL;
114 }
115
116 conf->ux.uid = user->pw_uid;
117 return 0;
118}
119
120/* Note: must not be declared <const> as its list will be overwritten.
121 * Please take care of keeping this list alphabetically sorted, doing so helps
122 * all code contributors.
123 * Optional keywords are also declared with a NULL ->parse() function so that
124 * the config parser can report an appropriate error when a known keyword was
125 * not enabled.
126 */
127static struct bind_kw_list bind_kws = { "UNIX", { }, {
128 { "gid", bind_parse_gid, 1 }, /* set the socket's gid */
129 { "group", bind_parse_group, 1 }, /* set the socket's gid from the group name */
130 { "mode", bind_parse_mode, 1 }, /* set the socket's mode (eg: 0644)*/
131 { "uid", bind_parse_uid, 1 }, /* set the socket's uid */
132 { "user", bind_parse_user, 1 }, /* set the socket's uid from the user name */
133 { NULL, NULL, 0 },
134}};
135
136INITCALL1(STG_REGISTER, bind_register_keywords, &bind_kws);