can now become another user
Costa Tsaousis (ktsaou) committed
Mar 27, 2014 at 03:09 UTC
78df830a0a8aff0f3b95f37493066b9f22c53f9b
4 files changed
+107
-79
netdata.c
+60
-7
@@ -6,6 +6,7 @@
6
#include <string.h>
7
#include <time.h>
8
#include <unistd.h>
9
+#include <pwd.h>
10
#include <sys/types.h>
11
#include <sys/time.h>
12
@@ -933,9 +934,15 @@ int mysendfile(struct web_client *w, char *filename)
934
return 400;
935
}
936
937
+ // access the file in web/*
938
+ char webfilename[FILENAME_MAX + 1];
939
+ strcpy(webfilename, "web/");
940
+ strncpy(&webfilename[4], filename, FILENAME_MAX - 4);
941
+ webfilename[FILENAME_MAX] = '\0';
942
+
943
// check if the file exists
944
struct stat stat;
938
- if(lstat(filename, &stat) != 0) {
945
+ if(lstat(webfilename, &stat) != 0) {
946
debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not found.", w->id, filename);
947
w->data->bytes = sprintf(w->data->buffer, "File '%s' does not exist, or is not accessible.", filename);
948
return 404;
@@ -949,7 +956,7 @@ int mysendfile(struct web_client *w, char *filename)
956
}
957
958
// open the file
952
- w->ifd = open(filename, O_NONBLOCK, O_RDONLY);
959
+ w->ifd = open(webfilename, O_NONBLOCK, O_RDONLY);
960
if(w->ifd == -1) {
961
w->ifd = w->ofd;
962
@@ -2023,6 +2030,33 @@ void sig_handler(int signo)
2030
}
2031
}
2032
2033
+int become_user(const char *username)
2034
+{
2035
+ struct passwd *pw = getpwnam(username);
2036
+ if(!pw) {
2037
+ fprintf(stderr, "User %s is not present. Error: %s\n", username, strerror(errno));
2038
+ return -1;
2039
+ }
2040
+ if(setgid(pw->pw_gid) != 0) {
2041
+ fprintf(stderr, "Cannot switch to user's %s group (gid: %d). Error: %s\n", username, pw->pw_gid, strerror(errno));
2042
+ return -1;
2043
+ }
2044
+ if(setegid(pw->pw_gid) != 0) {
2045
+ fprintf(stderr, "Cannot effectively switch to user's %s group (gid: %d). Error: %s\n", username, pw->pw_gid, strerror(errno));
2046
+ return -1;
2047
+ }
2048
+ if(setuid(pw->pw_uid) != 0) {
2049
+ fprintf(stderr, "Cannot switch to user %s (uid: %d). Error: %s\n", username, pw->pw_uid, strerror(errno));
2050
+ return -1;
2051
+ }
2052
+ if(seteuid(pw->pw_uid) != 0) {
2053
+ fprintf(stderr, "Cannot effectively switch to user %s (uid: %d). Error: %s\n", username, pw->pw_uid, strerror(errno));
2054
+ return -1;
2055
+ }
2056
+
2057
+ return(0);
2058
+}
2059
+
2060
int main(int argc, char **argv)
2061
{
2062
int i, daemon = 0;
@@ -2032,7 +2066,7 @@ int main(int argc, char **argv)
2066
if(strcmp(argv[i], "-l") == 0 && (i+1) < argc) {
2067
save_history = atoi(argv[i+1]);
2068
if(save_history < 5 || save_history > HISTORY_MAX) {
2035
- error("Invalid save lines %d given. Defaulting to %d.", save_history, HISTORY);
2069
+ fprintf(stderr, "Invalid save lines %d given. Defaulting to %d.\n", save_history, HISTORY);
2070
save_history = HISTORY;
2071
}
2072
else {
@@ -2041,9 +2075,19 @@ int main(int argc, char **argv)
2075
i++;
2076
}
2077
else if(strcmp(argv[i], "-u") == 0 && (i+1) < argc) {
2078
+ if(become_user(argv[i+1]) != 0) {
2079
+ fprintf(stderr, "Cannot become user %s.\n", argv[i+1]);
2080
+ exit(1);
2081
+ }
2082
+ else {
2083
+ debug(D_OPTIONS, "Successfully became user %s.", argv[i+1]);
2084
+ }
2085
+ i++;
2086
+ }
2087
+ else if(strcmp(argv[i], "-t") == 0 && (i+1) < argc) {
2088
update_every = atoi(argv[i+1]);
2089
if(update_every < 1 || update_every > 600) {
2046
- error("Invalid update timer %d given. Defaulting to %d.", update_every, UPDATE_EVERY_MAX);
2090
+ fprintf(stderr, "Invalid update timer %d given. Defaulting to %d.\n", update_every, UPDATE_EVERY_MAX);
2091
update_every = UPDATE_EVERY;
2092
}
2093
else {
@@ -2054,7 +2098,7 @@ int main(int argc, char **argv)
2098
else if(strcmp(argv[i], "-p") == 0 && (i+1) < argc) {
2099
listen_port = atoi(argv[i+1]);
2100
if(listen_port < 1 || listen_port > 65535) {
2057
- error("Invalid listen port %d given. Defaulting to %d.", listen_port, LISTEN_PORT);
2101
+ fprintf(stderr, "Invalid listen port %d given. Defaulting to %d.\n", listen_port, LISTEN_PORT);
2102
listen_port = LISTEN_PORT;
2103
}
2104
else {
@@ -2071,19 +2115,28 @@ int main(int argc, char **argv)
2115
fprintf(stderr, "\nUSAGE: %s [-d] [-l LINES_TO_SAVE] [-u UPDATE_TIMER] [-p LISTEN_PORT].\n\n", argv[0]);
2116
fprintf(stderr, " -d enable daemon mode (run in background).\n");
2117
fprintf(stderr, " -l LINES_TO_SAVE can be from 5 to %d lines in JSON data. Default: %d.\n", HISTORY_MAX, HISTORY);
2074
- fprintf(stderr, " -u UPDATE_TIMER can be from 1 to %d seconds. Default: %d.\n", UPDATE_EVERY_MAX, UPDATE_EVERY);
2118
+ fprintf(stderr, " -t UPDATE_TIMER can be from 1 to %d seconds. Default: %d.\n", UPDATE_EVERY_MAX, UPDATE_EVERY);
2119
fprintf(stderr, " -p LISTEN_PORT can be from 1 to %d. Default: %d.\n", 65535, LISTEN_PORT);
2120
+ fprintf(stderr, " -u USERNAME can be any system username to run as. Default: none.\n");
2121
exit(1);
2122
}
2123
}
2124
2125
+ // never become a problem
2126
+ if(nice(20) == -1) {
2127
+ fprintf(stderr, "Cannot lower my CPU priority. Error %s.\n", strerror(errno));
2128
+ }
2129
+
2130
if(daemon) {
2131
i = fork();
2132
if(i == -1) {
2133
perror("cannot fork");
2134
exit(1);
2135
}
2086
- if(i != 0) exit(0); // the parent
2136
+ if(i != 0) {
2137
+ fprintf(stderr, "Running in the background...\n");
2138
+ exit(0); // the parent
2139
+ }
2140
close(0);
2141
close(1);
2142
close(2);
netdata.start
+47
-72
@@ -2,7 +2,7 @@
2
3
base="`dirname "$0"`"
4
5
-if [ ! -d "$base" -o ! -f "$base/netdata.c" ]
5
+if [ ! -d "$base" -o ! -f "$base/netdata.c" -o ! -d "$base/web" ]
6
then
7
echo >&2 "Cannot find my home directory '${base}'."
8
exit 1
@@ -26,6 +26,16 @@ NETDATA_CONFIG_HISTORY_DATA=3600
26
# when refreshes graphs
27
NETDATA_CONFIG_RELOAD_EVERY=500
28
29
+# the user to run netdata under
30
+NETDATA_CONFIG_USER=nobody
31
+
32
+# set to 1, to enable debugging
33
+NETDATA_CONFIG_DEBUG=0
34
+
35
+# our port
36
+NETDATA_CONFIG_PORT=19999
37
+
38
+# get user configuration
39
if [ -f netdata.conf ]
40
then
41
source netdata.conf
@@ -34,75 +44,36 @@ fi
44
# how many history lines to keep in netdata
45
NETDATA_HISTORY_LINES=$[NETDATA_CONFIG_UPDATE_EVERY * NETDATA_CONFIG_HISTORY_POINTS / NETDATA_CONFIG_INTERNAL_UPDATE_EVERY]
46
37
-echo "Creating a directory for netdata..."
38
-data=
39
-for x in /run/netdata /var/run/netdata /tmp/netdata
40
-do
41
- echo " Trying '${x}'..."
42
- if [ ! -d "${x}" ]
43
- then
44
- mkdir "${x}" 2>/dev/null
45
- if [ $? -eq 0 ]
46
- then
47
- echo " OK. '${x}' works."
48
- data="${x}"
49
- break
50
- fi
51
- else
52
- echo " OK. '${x}' works."
53
- data="${x}"
54
- break
55
- fi
56
-done
57
-
58
-if [ -z "${data}" ]
59
-then
60
- echo >&2 "Cannot find where to put netdata files."
61
- exit 1
62
-fi
63
-
64
-if [ -h data ]
65
-then
66
- echo "Removing existing $base/data link"
67
- rm data || exit 1
68
-fi
69
-
70
-if [ ! -d data ]
71
-then
72
- echo "Linking '${data}' to $base/data"
73
- ln -s "${data}" data || exit 1
74
-else
75
- echo >&2 "Directory $base/data already exists. Not touching it, however it should be a link '${data}'."
76
-fi
77
-
78
-cp "${base}/all.xsl" "${data}/"
79
-cp "${base}/netdata.js" "${data}/"
80
-cp "${base}/tc-all.sh" "${data}/"
81
-chmod 700 "${data}/tc-all.sh"
82
-
83
-echo "Finding proper parameters for dashboard..."
84
-
47
echo "Stopping a (possibly) running netdata..."
48
killall netdata 2>/dev/null
49
killall tc-all.sh 2>/dev/null
88
-
50
sleep 2
51
52
echo "Compiling netdata"
92
-# gcc -Wall -O3 -o netdata netdata.c -lpthread || exit 1
93
-gcc -Wall -ggdb -o netdata netdata.c -lpthread || exit 1
53
+if [ $NETDATA_CONFIG_DEBUG -eq 1 ]
54
+then
55
+ ulimit -c unlimited
56
+ gcc -Wall -ggdb -o netdata netdata.c -lpthread || exit 1
57
+else
58
+ gcc -Wall -O3 -o netdata netdata.c -lpthread || exit 1
59
+fi
60
61
echo "Starting netdata"
96
-p=`pwd`
97
-cd data
98
-ulimit -c unlimited
99
-$p/netdata -d -u $NETDATA_CONFIG_INTERNAL_UPDATE_EVERY -l $NETDATA_HISTORY_LINES || exit 1
100
-cd "$p"
101
-
62
+if [ "$USER" = "root" ]
63
+then
64
+ chown -R "$NETDATA_CONFIG_USER" web || exit 1
65
+ chmod 0775 web || exit 1
66
+ chmod -R 0664 web/* || exit 1
67
+ ./netdata -d -u $NETDATA_CONFIG_USER -t $NETDATA_CONFIG_INTERNAL_UPDATE_EVERY -l $NETDATA_HISTORY_LINES -p $NETDATA_CONFIG_PORT || exit 1
68
+else
69
+ echo >&2 "WARNING: NOT RUNNING AS ROOT - CANNOT SWITCH TO USER $NETDATA_CONFIG_USER"
70
+ echo >&2 "WARNING: MAKE SURE FILES IN web/ ARE OWNED BY $USER - or it will not work"
71
+ ./netdata -d -t $NETDATA_CONFIG_INTERNAL_UPDATE_EVERY -l $NETDATA_HISTORY_LINES -p $NETDATA_CONFIG_PORT || exit 1
72
+fi
73
sleep 2
74
75
# count all graphs
105
-all=`wget http://127.0.0.1:19999/list -O - 2>/dev/null`
76
+all=`wget http://127.0.0.1:$NETDATA_CONFIG_PORT/list -O - 2>/dev/null`
77
count=0
78
for x in $all
79
do
@@ -116,9 +87,9 @@ done
87
88
echo "We have $count graphs..."
89
119
-echo "Generating ${data}/index.html"
90
+echo "Generating web/index.html"
91
host="`hostname`"
121
-cat >${data}/index.html <<EOF
92
+cat >web/index.html <<EOF
93
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
94
<html xmlns="http://www.w3.org/1999/xhtml">
95
<style>
@@ -175,13 +146,13 @@ do
146
eval "p=\${NETDATA_PRIORITY_${y}}"
147
if [ ! "$p" = "IGNORE" ]
148
then
178
- cat >>${data}/index.html <<EOF2
149
+ cat >>web/index.html <<EOF2
150
addChart('${x}', '${y}_div', 0, 0, "data/${x}/${NETDATA_CONFIG_HISTORY_POINTS}/${NETDATA_CONFIG_UPDATE_EVERY}/average/", "${title}${t} (${x})", "${vtitle}");
151
EOF2
152
fi
153
done
154
184
-cat >>${data}/index.html <<EOF3
155
+cat >>web/index.html <<EOF3
156
refreshCharts(999999);
157
}
158
@@ -225,25 +196,29 @@ done >"${tmp}"
196
for x in `cat "${tmp}" | sort`
197
do
198
n="`echo "$x" | cut -d '|' -f 2-`"
228
- cat >>${data}/index.html <<EOF4
199
+ cat >>web/index.html <<EOF4
200
<div id="${n}_div"></div>
201
EOF4
202
done
203
rm -f "${tmp}"
204
234
-cat >>${data}/index.html <<EOF5
205
+cat >>web/index.html <<EOF5
206
</body>
207
</html>
208
EOF5
209
239
-set|grep ^NETDATA_ >netdata.conf
240
-
241
-if [ ! -h "${data}/data" ]
210
+if [ "$USER" = "root" ]
211
then
243
- cd "${data}"
244
- ln -s . data
212
+ chown -R "$NETDATA_CONFIG_USER" web || exit 1
213
+ chmod 0775 web || exit 1
214
+ chmod -R 0664 web/* || exit 1
215
fi
216
247
-echo "All Done."
248
-echo "Just hit http://127.0.0.1:19999/ from your browser."
217
+# save config back
218
+set|grep ^NETDATA_ >netdata.conf
219
220
+echo "All Done."
221
+echo "Just hit http://127.0.0.1:$NETDATA_CONFIG_PORT/ from your browser."
222
+echo
223
+echo "You can edit config options in file netdata.conf"
224
+echo