]> andersk Git - moira.git/blame - server/mr_scall.c
Implement AUTH_002, which isn't vulnerable to replay attacks. Remove
[moira.git] / server / mr_scall.c
CommitLineData
a3cf6921 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
c801de4c 7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
a3cf6921 9 *
a3cf6921 10 */
11
12#ifndef lint
13static char *rcsid_sms_scall_c = "$Header$";
14#endif lint
15
c801de4c 16#include <mit-copyright.h>
57c08162 17#include <sys/types.h>
18#include <sys/stat.h>
9cad7c8f 19#include <sys/file.h>
03c05291 20#include <fcntl.h>
21#include <string.h>
960b073b 22#include <arpa/inet.h>
a3cf6921 23#include <krb.h>
78849033 24#include <errno.h>
d548a4e7 25#include "mr_server.h"
03c05291 26#include "query.h"
a3cf6921 27extern char buf1[];
28extern int nclients;
29extern char *whoami;
8165c536 30extern int errno;
a3cf6921 31
32extern void clist_delete(), do_auth(), do_shutdown();
33void do_call();
03c05291 34extern int dbms_errno, mr_errcode;
78543660 35static int row_count;
36
37/* Put this in a variable so that we can patch it if necessary */
50e114e1 38int max_row_count = 4096;
a3cf6921 39
40/*
41 * Welcome to the (finite state) machine (highest level).
42 */
43void
44do_client(cp)
45 client *cp;
46{
57c08162 47 struct stat stbuf;
48
ed31e0d1 49 free_rtn_tuples(cp);
a3cf6921 50 if (OP_STATUS(cp->pending_op) == OP_CANCELLED) {
a36b5bd7 51 com_err(whoami, 0, "Closed connection (now %d client%s, %d new queries, %d old)",
f17535a4 52 nclients-1,
a36b5bd7 53 nclients!=2?"s":"",
54 newqueries,
55 oldqueries);
a3cf6921 56 clist_delete(cp);
57c08162 57 /* if we no longer have any clients, and we're supposed to
58 * go down, then go down now.
59 */
60 if ((dormant == AWAKE) && (nclients == 0) &&
d548a4e7 61 (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) {
57c08162 62 com_err(whoami, 0, "motd file exists, slumbertime");
63 dormant = SLEEPY;
64 }
a3cf6921 65 return;
66 }
67 switch (cp->action) {
68 case CL_ACCEPT:
69 case CL_SEND:
70 /* Start recieving next request */
d548a4e7 71 initialize_operation(cp->pending_op, mr_start_recv,
5dbd09a0 72 (char *)&cp->args, (int (*)())NULL);
a3cf6921 73 queue_operation(cp->con, CON_INPUT, cp->pending_op);
74 cp->action = CL_RECEIVE;
75 break;
76 case CL_RECEIVE:
77 /* Data is here. Process it & start it heading back */
78 do_call(cp); /* This may block for a while. */
d548a4e7 79 mr_destroy_reply(cp->args);
de24f12d 80 cp->args = NULL;
d548a4e7 81 initialize_operation(cp->pending_op, mr_start_send,
5dbd09a0 82 (char *)&cp->reply, (int (*)())NULL);
a3cf6921 83 queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
84 cp->action = CL_SEND;
85 break;
86 }
87}
88
a3cf6921 89char *procnames[] = {
90 "noop",
91 "auth",
92 "shutdown",
78849033 93 "query",
630e8323 94 "access",
57c08162 95 "dcm",
96 "motd",
630e8323 97};
98
a3cf6921 99
100void
101do_call(cl)
102 client *cl;
103{
104 int pn;
d548a4e7 105 cl->reply.mr_argc = 0;
106 cl->reply.mr_status = 0;
107 cl->reply.mr_version_no = cl->args->mr_version_no;
108 if (((pn = cl->args->mr_procno) < 0) ||
109 (pn > MR_MAX_PROC)) {
a3cf6921 110 com_err(whoami, 0, "procno out of range");
d548a4e7 111 cl->reply.mr_status = MR_UNKNOWN_PROC;
a3cf6921 112 return;
113 }
630e8323 114 if (log_flags & LOG_ARGS)
d548a4e7 115 log_args(procnames[pn], cl->args->mr_version_no,
116 cl->args->mr_argc, cl->args->mr_argv);
630e8323 117 else if (log_flags & LOG_REQUESTS)
f17535a4 118 com_err(whoami, 0, "%s", procnames[pn]);
a3cf6921 119
57c08162 120 if ((dormant == ASLEEP || dormant == GROGGY) &&
d548a4e7 121 pn != MR_NOOP && pn != MR_MOTD) {
122 cl->reply.mr_status = MR_DOWN;
57c08162 123 if (log_flags & LOG_RES)
d548a4e7 124 com_err(whoami, MR_DOWN, "(query refused)");
57c08162 125 return;
126 }
127
4ce8321c 128 /* make sure this gets cleared before every operation */
03c05291 129 dbms_errno = 0;
4ce8321c 130
a3cf6921 131 switch(pn) {
d548a4e7 132 case MR_NOOP:
133 cl->reply.mr_status = 0;
a3cf6921 134 return;
3630192b 135
d548a4e7 136 case MR_AUTH:
a3cf6921 137 do_auth(cl);
138 return;
78849033 139
d548a4e7 140 case MR_QUERY:
a3cf6921 141 do_retr(cl);
142 return;
a3cf6921 143
d548a4e7 144 case MR_ACCESS:
3630192b 145 do_access(cl);
146 return;
147
d548a4e7 148 case MR_SHUTDOWN:
a3cf6921 149 do_shutdown(cl);
150 return;
8165c536 151
d548a4e7 152 case MR_DO_UPDATE:
a36b5bd7 153 trigger_dcm(0, 0, cl);
8165c536 154 return;
57c08162 155
d548a4e7 156 case MR_MOTD:
57c08162 157 get_motd(cl);
158 return;
a3cf6921 159 }
160}
161
ed31e0d1 162free_rtn_tuples(cp)
163 client *cp;
164{
165 register returned_tuples *temp;
166 for (temp=cp->first; temp && OP_DONE(temp->op); ) {
167 register returned_tuples *t1=temp;
168 temp = t1->next;
169 if (t1 == cp->last) cp->last = NULL;
28222705 170
d548a4e7 171 mr_destroy_reply(t1->retval);
ed31e0d1 172 delete_operation(t1->op);
173 free(t1);
174 }
175 cp->first = temp;
176}
177
78849033 178retr_callback(argc, argv, p_cp)
28222705 179 register int argc;
180 register char **argv;
78849033 181 char *p_cp;
182{
183 register client *cp = (client *)p_cp;
78543660 184 mr_params *arg_tmp;
185 returned_tuples *tp;
186 OPERATION op_tmp;
187 register char **nargv;
188 register int i;
189
190 if (row_count++ >= max_row_count) {
03c05291 191 dbms_errno = mr_errcode = MR_NO_MEM;
78543660 192 return;
193 }
194
78849033 195 /*
196 * This takes too much advantage of the fact that
197 * serialization of the data happens during the queue operation.
198 */
78543660 199 arg_tmp = (mr_params *)db_alloc(sizeof(mr_params));
200 tp = (returned_tuples *)db_alloc(sizeof(returned_tuples));
201 nargv = (char **)malloc(argc * sizeof(char *));
ed31e0d1 202
78543660 203 op_tmp = create_operation();
78849033 204
d548a4e7 205 if (mr_trim_args(argc, argv) == MR_NO_MEM) {
206 com_err(whoami, MR_NO_MEM, "while trimming args");
a36b5bd7 207 }
630e8323 208 if (log_flags & LOG_RESP)
d548a4e7 209 log_args("return: ", cp->args->mr_version_no, argc, argv);
630e8323 210
ed31e0d1 211 tp->op = op_tmp;
212 tp->retval = arg_tmp;
213 tp->next = NULL;
78849033 214
d548a4e7 215 arg_tmp->mr_status = MR_MORE_DATA;
216 arg_tmp->mr_version_no = cp->args->mr_version_no;
217 arg_tmp->mr_argc = argc;
218 arg_tmp->mr_argv = nargv;
28222705 219 for (i = 0; i < argc; i++) {
220 register int len = strlen(argv[i]) + 1;
221 nargv[i] = malloc(len);
03c05291 222 memcpy(nargv[i], argv[i], len);
28222705 223 }
d548a4e7 224 arg_tmp->mr_flattened = (char *)NULL;
225 arg_tmp->mr_argl = (int *)NULL;
ed31e0d1 226
227 if (cp->last) {
228 cp->last->next = tp;
229 cp->last = tp;
230 } else {
231 cp->last = cp->first = tp;
232 }
233
78849033 234 reset_operation(op_tmp);
d548a4e7 235 initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp,
78849033 236 (int (*)())NULL);
237 queue_operation(cp->con, CON_OUTPUT, op_tmp);
238}
239
de24f12d 240list_users(callbk, callarg)
241 int (*callbk)();
242 char *callarg;
243{
244 char *argv[6];
245 char buf[30];
246 char buf1[30];
247 int i;
248 extern client **clients;
de24f12d 249 char *cp;
de24f12d 250 char *ctime();
251
252 for (i = 0; i < nclients; i++) {
253 register client *cl = clients[i];
254 if (cl->clname)
255 argv[0] = cl->clname;
256 else argv[0] = "unauthenticated";
257
258 argv[1] = inet_ntoa(cl->haddr.sin_addr);
259 argv[2] = buf;
260 sprintf(buf, "port %d", ntohs(cl->haddr.sin_port));
261 argv[3] = ctime(&cl->last_time_used);
03c05291 262 cp = strchr(argv[3], '\n');
de24f12d 263 if (cp) *cp = '\0';
264 argv[4] = buf1;
265 sprintf(buf1, "[#%d]", cl->id);
266 (*callbk)(5, argv, callarg);
267 }
268 return 0;
269}
78849033 270
a3cf6921 271do_retr(cl)
de24f12d 272 register client *cl;
a3cf6921 273{
de24f12d 274 register char *queryname;
275
d548a4e7 276 cl->reply.mr_argc = 0;
277 cl->reply.mr_status = 0;
78543660 278 row_count = 0;
630e8323 279
c473dda1 280 if (cl->args->mr_argc < 1) {
281 cl->reply.mr_status = MR_ARGS;
282 com_err(whoami, MR_ARGS, "got nameless query");
283 return;
284 }
d548a4e7 285 queryname = cl->args->mr_argv[0];
de24f12d 286
d548a4e7 287 if (cl->args->mr_version_no == MR_VERSION_2)
a36b5bd7 288 newqueries++;
289 else
290 oldqueries++;
291
de24f12d 292 if (strcmp(queryname, "_list_users") == 0)
d548a4e7 293 cl->reply.mr_status = list_users(retr_callback, (char *)cl);
de24f12d 294 else {
d548a4e7 295 cl->reply.mr_status =
296 mr_process_query(cl,
c473dda1 297 queryname,
d548a4e7 298 cl->args->mr_argc-1,
299 cl->args->mr_argv+1,
de24f12d 300 retr_callback,
301 (char *)cl);
302 }
78543660 303 if (row_count >= max_row_count) {
304 critical_alert("moirad", "attempted query %s with %d rows\n",
305 queryname, row_count);
306 }
307
630e8323 308 if (log_flags & LOG_RES)
309 com_err(whoami, 0, "Query complete.");
a3cf6921 310}
78849033 311
3630192b 312do_access(cl)
313 client *cl;
314{
c473dda1 315 if (cl->args->mr_argc < 1) {
316 cl->reply.mr_status = MR_ARGS;
317 com_err(whoami, MR_ARGS, "got nameless access");
318 return;
319 }
d548a4e7 320 cl->reply.mr_argc = 0;
630e8323 321
d548a4e7 322 cl->reply.mr_status =
323 mr_check_access(cl,
324 cl->args->mr_argv[0],
325 cl->args->mr_argc-1,
326 cl->args->mr_argv+1);
3630192b 327
328 com_err(whoami, 0, "Access check complete.");
329}
8165c536 330
a36b5bd7 331
332/* trigger_dcm is also used as a followup routine to the
333 * set_server_host_override query, hence the two dummy arguments.
334 */
335
8165c536 336struct query pseudo_query = {
337 "trigger_dcm",
338 "tdcm",
339};
340
a36b5bd7 341trigger_dcm(dummy0, dummy1, cl)
342 int dummy0, dummy1;
8165c536 343 client *cl;
344{
345 register int pid;
185f76ce 346 char prog[128];
347
d548a4e7 348 cl->reply.mr_argc = 0;
8165c536 349
d548a4e7 350 if (cl->reply.mr_status = check_query_access(&pseudo_query, 0, cl) )
351 return(cl->reply.mr_status);
8165c536 352
185f76ce 353 sprintf(prog, "%s/startdcm", BIN_DIR);
8165c536 354 pid = vfork();
355 switch (pid) {
356 case 0:
185f76ce 357 execl(prog, "startdcm", 0);
8165c536 358 exit(1);
359
360 case -1:
d548a4e7 361 cl->reply.mr_status = errno;
a36b5bd7 362 return(0);
8165c536 363
364 default:
a36b5bd7 365 return(0);
8165c536 366 }
367}
368
57c08162 369
370get_motd(cl)
371client *cl;
372{
9cad7c8f 373 int motd, len;
57c08162 374 char buffer[1024];
375 char *arg[1];
376
377 arg[0] = buffer;
d548a4e7 378 cl->reply.mr_status = 0;
379 motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
9cad7c8f 380 if (motd < 0) return;
381 len = read(motd, buffer, sizeof(buffer) - 1);
382 close(motd);
383 buffer[len] = 0;
78543660 384 row_count = 0;
57c08162 385 retr_callback(1, arg, cl);
d548a4e7 386 cl->reply.mr_status = 0;
57c08162 387}
This page took 0.155427 seconds and 5 git commands to generate.