1 /*----------------------------------------------------------------------------*/
2 /* Xymon webpage generator tool. */
3 /* */
4 /* Copyright (C) 2004-2011 Henrik Storner <henrik@storner.dk> */
5 /* */
6 /* This program is released under the GNU General Public License (GPL), */
7 /* version 2. See the file "COPYING" for details. */
8 /* */
9 /*----------------------------------------------------------------------------*/
10
11 static char rcsid[] = "$Id: useradm.c 6588 2010-11-14 17:21:19Z storner $";
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16 #include <sys/wait.h>
17 #include <unistd.h>
18
19 #include "libxymon.h"
20
errormsg(char * msg)21 static void errormsg(char *msg)
22 {
23 printf("Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE"));
24 printf("<html><head><title>Invalid request</title></head>\n");
25 printf("<body>%s</body></html>\n", msg);
26 exit(1);
27 }
28
idcompare(const void * p1,const void * p2)29 static int idcompare(const void *p1, const void *p2)
30 {
31 return strcmp(* (char * const *) p1, * (char * const *) p2);
32 }
33
34 #define ACT_NONE 0
35 #define ACT_CREATE 1
36 #define ACT_DELETE 2
37
38 char *adduser_name = NULL;
39 char *adduser_password = NULL;
40 char *deluser_name = NULL;
41
parse_query(void)42 int parse_query(void)
43 {
44 cgidata_t *cgidata, *cwalk;
45 int returnval = ACT_NONE;
46
47 cgidata = cgi_request();
48 if (cgi_method != CGI_POST) return ACT_NONE;
49
50 if (cgidata == NULL) errormsg(cgi_error());
51
52 cwalk = cgidata;
53 while (cwalk) {
54 /*
55 * cwalk->name points to the name of the setting.
56 * cwalk->value points to the value (may be an empty string).
57 */
58
59 if (strcmp(cwalk->name, "USERNAME") == 0) {
60 adduser_name = cwalk->value;
61 }
62 else if (strcmp(cwalk->name, "PASSWORD") == 0) {
63 adduser_password = cwalk->value;
64 }
65 else if (strcmp(cwalk->name, "USERLIST") == 0) {
66 deluser_name = cwalk->value;
67 }
68 else if (strcmp(cwalk->name, "SendCreate") == 0) {
69 returnval = ACT_CREATE;
70 }
71 else if (strcmp(cwalk->name, "SendDelete") == 0) {
72 returnval = ACT_DELETE;
73 }
74
75 cwalk = cwalk->next;
76 }
77
78 /* We only want to accept posts from certain pages */
79 if (returnval != ACT_NONE) {
80 char cgisource[1024]; char *p;
81 p = csp_header("useradm"); if (p) fprintf(stdout, "%s", p);
82 snprintf(cgisource, sizeof(cgisource), "%s/%s", xgetenv("SECURECGIBINURL"), "useradm");
83 if (!cgi_refererok(cgisource)) { fprintf(stdout, "Location: %s.sh?\n\n", cgisource); return 0; }
84 }
85
86 return returnval;
87 }
88
main(int argc,char * argv[])89 int main(int argc, char *argv[])
90 {
91 int argi, event;
92 char *envarea = NULL;
93 char *hffile = "useradm";
94 SBUF_DEFINE(passfile);
95 FILE *fd;
96 char *infomsg = NULL;
97
98 for (argi = 1; (argi < argc); argi++) {
99 if (argnmatch(argv[argi], "--env=")) {
100 char *p = strchr(argv[argi], '=');
101 loadenv(p+1, envarea);
102 }
103 else if (argnmatch(argv[argi], "--area=")) {
104 char *p = strchr(argv[argi], '=');
105 envarea = strdup(p+1);
106 }
107 else if (strcmp(argv[argi], "--debug") == 0) {
108 debug = 1;
109 }
110 else if (argnmatch(argv[argi], "--passwdfile=")) {
111 char *p = strchr(argv[argi], '=');
112 passfile = strdup(p+1);
113 }
114 }
115
116 if (passfile == NULL) {
117 SBUF_MALLOC(passfile, strlen(xgetenv("XYMONHOME")) + 20);
118 snprintf(passfile, passfile_buflen, "%s/etc/xymonpasswd", xgetenv("XYMONHOME"));
119 }
120
121 event = parse_query();
122
123 if (adduser_name && !issimpleword(adduser_name)) {
124 event = ACT_NONE;
125 adduser_name = strdup("");
126 infomsg = "<strong><big><font color='#FF0000'>Invalid USERNAME. Letters, numbers, dashes, and periods only.</font></big></strong>\n";
127 }
128
129 switch (event) {
130 case ACT_NONE: /* Show the form */
131 break;
132
133
134 case ACT_CREATE: /* Add a user */
135 {
136 pid_t childpid;
137 int n, ret;
138
139 childpid = fork();
140 if (childpid < 0) {
141 /* Fork failed */
142 errprintf("Could not fork child\n");
143 exit(1);
144 }
145 else if (childpid == 0) {
146 /* child */
147 char *cmd;
148 char **cmdargs;
149
150 cmdargs = (char **) calloc(4 + 2, sizeof(char *));
151 cmdargs[0] = cmd = strdup("htpasswd");
152 cmdargs[1] = "-b";
153 cmdargs[2] = strdup(passfile);
154 cmdargs[3] = strdup(adduser_name);
155 cmdargs[4] = strdup(adduser_password);
156 cmdargs[5] = '\0';
157
158 execvp(cmd, cmdargs);
159 exit(127);
160 }
161
162 /* parent waits for htpasswd to finish */
163 if ((waitpid(childpid, &n, 0) == -1) || (WEXITSTATUS(n) != 0)) {
164 infomsg = "Update FAILED";
165
166 }
167 else {
168 infomsg = "User added/updated";
169 }
170 }
171 break;
172
173
174 case ACT_DELETE: /* Delete a user */
175 {
176 pid_t childpid;
177 int n, ret;
178
179 childpid = fork();
180 if (childpid < 0) {
181 /* Fork failed */
182 errprintf("Could not fork child\n");
183 exit(1);
184 }
185 else if (childpid == 0) {
186 /* child */
187 char *cmd;
188 char **cmdargs;
189
190 cmdargs = (char **) calloc(3 + 2, sizeof(char *));
191 cmdargs[0] = cmd = strdup("htpasswd");
192 cmdargs[1] = "-D";
193 cmdargs[2] = strdup(passfile);
194 cmdargs[3] = strdup(deluser_name);
195 cmdargs[4] = '\0';
196
197 execvp(cmd, cmdargs);
198 exit(127);
199 }
200
201 /* parent waits for htpasswd to finish */
202 if ((waitpid(childpid, &n, 0) == -1) || (WEXITSTATUS(n) != 0)) {
203 infomsg = "Update delete FAILED";
204
205 }
206 else {
207 infomsg = "User deleted";
208 }
209 }
210 break;
211 }
212
213 sethostenv_clearlist(NULL);
214 sethostenv_addtolist(NULL, "", "", NULL, 1); /* Have a blank entry first so we won't delete one by accident */
215 fd = fopen(passfile, "r");
216
217 if (fd != NULL) {
218 char l[1024];
219 char *id, *delim;
220 int usercount;
221 char **userlist;
222 int i;
223
224 usercount = 0;
225 userlist = (char **)calloc(usercount+1, sizeof(char *));
226
227 while (fgets(l, sizeof(l), fd)) {
228 id = l; delim = strchr(l, ':');
229 if (delim) {
230 *delim = '\0';
231 usercount++;
232 userlist = (char **)realloc(userlist, (usercount+1)*sizeof(char *));
233 userlist[usercount-1] = strdup(id);
234 userlist[usercount] = NULL;
235 }
236 }
237
238 fclose(fd);
239
240 qsort(&userlist[0], usercount, sizeof(char *), idcompare);
241 for (i=0; (userlist[i]); i++) sethostenv_addtolist(NULL, userlist[i], userlist[i], NULL, 0);
242 }
243
244 fprintf(stdout, "Content-type: %s\n\n", xgetenv("HTMLCONTENTTYPE"));
245
246 showform(stdout, hffile, "useradm_form", COL_BLUE, getcurrenttime(NULL), infomsg, NULL);
247
248 return 0;
249 }
250
251