]> mj.ucw.cz Git - moe.git/blob - submit/commands.c
Documented the protocol.
[moe.git] / submit / commands.c
1 /*
2  *  The Submit Daemon: High-Level Part of the Protocol
3  *
4  *  (c) 2007 Martin Mares <mj@ucw.cz>
5  */
6
7 #include "lib/lib.h"
8 #include "lib/mempool.h"
9 #include "lib/stkstring.h"
10 #include "sherlock/object.h"
11 #include "sherlock/objread.h"
12
13 #include <sys/stat.h>
14
15 #include "submitd.h"
16
17 /*** REQUESTS AND REPLIES ***/
18
19 static void NONRET
20 read_error_cb(struct obj_read_state *st UNUSED, byte *msg)
21 {
22   client_error("Request parse error: %s", msg);
23 }
24
25 static int
26 read_request(struct conn *c)
27 {
28   if (c->pool)
29     mp_flush(c->pool);
30   else
31     c->pool = mp_new(1024);
32   c->request = obj_new(c->pool);
33   c->reply = obj_new(c->pool);
34
35   struct obj_read_state st;
36   obj_read_start(&st, c->request);
37   st.error_callback = read_error_cb;
38   byte line[1024];
39   uns size = 0;
40   for (;;)
41     {
42       int l = bgets_nodie(&c->rx_fb, line, sizeof(line));
43       if (l < 0)
44         client_error("Request line too long");
45       if (!l)
46         {
47           if (!size)
48             return 0;
49           else
50             client_error("Truncated request");
51         }
52       if (l == 1)
53         break;
54       size += l;
55       if (size >= max_request_size)
56         client_error("Request too long");
57       obj_read_attr(&st, line[0], line+1);
58     }
59   obj_read_end(&st);
60   return 1;
61 }
62
63 static void
64 write_reply(struct conn *c)
65 {
66   if (trace_commands)
67     {
68       byte *msg;
69       if (msg = obj_find_aval(c->reply, '-'))
70         log(L_DEBUG, ">> -%s", msg);
71       else if (msg = obj_find_aval(c->reply, '+'))
72         log(L_DEBUG, ">> +%s", msg);
73       else
74         log(L_DEBUG, ">> ???");
75     }
76   put_attr_set_type(BUCKET_TYPE_PLAIN);
77   bput_object(&c->tx_fb, c->reply);
78   bputc(&c->tx_fb, '\n');
79   bflush(&c->tx_fb);
80 }
81
82 /*** COMMAND MUX ***/
83
84 static void
85 execute_command(struct conn *c)
86 {
87   byte *cmd = obj_find_aval(c->request, '!');
88   if (!cmd)
89     {
90       obj_set_attr(c->reply, '-', "Missing command");
91       return;
92     }
93   if (trace_commands)
94     log(L_DEBUG, "<< %s", cmd);
95   obj_set_attr(c->reply, '-', "Unknown command");
96 }
97
98 int
99 process_command(struct conn *c)
100 {
101   if (!read_request(c))
102     return 0;
103   execute_command(c);
104   write_reply(c);
105   return 1;
106 }
107
108 /*** INITIAL HANDSHAKE ***/
109
110 static int
111 user_exists_p(byte *user)
112 {
113   byte *fn = stk_printf("solutions/%s/status", user);
114   struct stat st;
115   return !stat(fn, &st) && S_ISREG(st.st_mode);
116 }
117
118 static void
119 execute_init(struct conn *c)
120 {
121   byte *user = obj_find_aval(c->request, 'U');
122   if (!user)
123     {
124       obj_set_attr(c->reply, '-', "Missing user");
125       return;
126     }
127   if (!c->cert_name ||
128       !strcmp(user, c->cert_name) ||
129       c->rule->allow_admin && !strcmp(c->cert_name, "admin"))
130     {
131       if (!user_exists_p(user))
132         {
133           obj_set_attr(c->reply, '-', "Unknown user");
134           return;
135         }
136       log(L_INFO, "Logged in %s", user);
137     }
138   else
139     {
140       obj_set_attr(c->reply, '-', "Permission denied");
141       log(L_ERROR, "Unauthorized attempt to log in as %s", user);
142       return;
143     }
144   obj_set_attr(c->reply, '+', "OK");
145   c->user = xstrdup(user);
146 }
147
148 int
149 process_init(struct conn *c)
150 {
151   if (!read_request(c))
152     return 0;
153   execute_init(c);
154   write_reply(c);
155   return !!obj_find_attr(c->reply, '+');
156 }