]> andersk Git - moira.git/blame - reg_svr/requests.c
do typed input on machine type
[moira.git] / reg_svr / requests.c
CommitLineData
9a83b251 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 *
8 * Server for user registration with SMS and Kerberos.
9 *
10 * This file handles the processing of requests for the register
11 * server.
12 */
13
14#ifndef lint
15static char *rcsid_requests_c = "$Header$";
16#endif lint
17
18/*
19 * Before you add anything to the list of things that are #included and
20 * #defined, make sure that it is not already done in reg_svr.h
21 */
22
23#include "reg_svr.h"
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <netdb.h>
27
28#define NUM_REQUESTS_SAVED 100 /* Number of transactions to save */
29#define CUR_REQ (requests[cur_request_index]) /* The current request */
30#define NEXT_INDEX(x) (x == NUM_REQUESTS_SAVED - 1) ? 0 : (x + 1)
31#define PREV_INDEX(x) (x == 0) ? (NUM_REQUESTS_SAVED - 1) : (x - 1)
32
33static struct servent *sp; /* Service info from /etc/services */
34static int s; /* Socket descriptor */
35static struct sockaddr_in sin; /* Internet style socket address */
36static int addrlen; /* Size of socket address (sin) */
37
38/* In order to elegantly handle multiple retransmissions, an instance
39 of this structure will be retained for the last NUM_REQUESTS_SAVED
40 transactions with the client. */
41struct request_save {
42 char out_pkt[BUFSIZ]; /* Buffer for outgoing packet */
43 int out_pktlen; /* Length of outgoing packet */
44 U_32BIT seqno; /* Sequence number for packet transmission */
45 u_long ip_address; /* Internet address of client host */
46 u_short cl_port; /* Port number client used */
47};
48
49static struct request_save requests[NUM_REQUESTS_SAVED]; /* Saved packets */
50static int cur_request_index = 0; /* Index to the current request */
51
52void clear_req(req)
53 struct request_save *req;
54{
55 req->seqno = 0;
56 req->ip_address = 0;
57 req->cl_port = 0;
58}
59
60void req_initialize()
61{
62 register int i;
63
64 /* Get service information from /etc/services */
65 if ((sp = getservbyname("sms_ureg", "udp")) == NULL)
66 {
67 com_err(whoami, errno, " unknown service sms_ureg/udp");
68 exit(1);
69 }
70
71 /* Get an internet style datagram socket */
72 if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
73 {
74 com_err(whoami,errno," socket");
75 exit(1);
76 }
77 bzero((char *)&sin,(int)sizeof(sin));
78
79 sin.sin_family = AF_INET;
80 sin.sin_port = sp->s_port;
81 sin.sin_addr.s_addr = INADDR_ANY;
82
83 /* Bind a name to the socket */
84 if (bind(s, &sin, sizeof(sin)) < 0)
85 {
86 com_err(whoami,errno," bind");
87 exit(1);
88 }
89
90 for (i = 0; i < NUM_REQUESTS_SAVED; i++)
91 clear_req(&(requests[i]));
92}
93
94int handle_retransmitted()
95{
96 register int i; /* A counter */
97 int status = FALSE; /* Return status */
98
99 for (i = PREV_INDEX(cur_request_index); i != cur_request_index;
100 i = PREV_INDEX(i))
101 {
102 if ((requests[i].seqno == CUR_REQ.seqno) &&
103 (requests[i].ip_address == sin.sin_addr.s_addr) &&
104 (requests[i].cl_port == sin.sin_port))
105 /* This is a retransmitted packet */
106 {
107#ifdef DEBUG
108 com_err(whoami, 0, "Retransmitted packet detected.");
109#endif
110 status = TRUE;
111 (void) sendto(s, requests[i].out_pkt, requests[i].out_pktlen,
112 0, &sin, addrlen);
113 break;
114 }
115 }
116
117 return status;
118}
119
120void respond(status,text)
121 int status; /* Return status for the client */
122 char *text; /* Text for the client */
123 /* This routine takes care of sending packets back to the client and
124 caching the necessary information for retransmission detection.
125 It is the only place in which cur_request_index should be
126 changed. */
127{
128 CUR_REQ.out_pktlen = sizeof(CUR_REQ.out_pkt);
129
130 if (format_pkt(CUR_REQ.out_pkt, &(CUR_REQ.out_pktlen),
131 CUR_REQ.seqno, status, text))
132 com_err(whoami,0,"Client error message was truncated.");
133 (void) sendto(s, CUR_REQ.out_pkt, CUR_REQ.out_pktlen, 0, &sin, addrlen);
134
135 cur_request_index = NEXT_INDEX(cur_request_index);
136}
137
138void get_request(message)
139 struct msg *message; /* Will contain formatted packet information */
140{
141 static char packet[BUFSIZ]; /* Buffer for incoming packet */
142 int pktlen; /* Length of incoming packet */
143 int status = FAILURE; /* Error status */
144
145 /* Sit around waiting for requests from the client. */
146 for (;;)
147 {
148 com_err(whoami, 0, "*** Ready for next request ***");
149 addrlen = sizeof(sin);
150 /* Receive a packet */
151 if ((pktlen = recvfrom(s,packet,sizeof(packet),0,&sin,&addrlen)) < 0)
152 {
153 com_err(whoami, errno, " recvfrom");
154 /* Don't worry if error is interrupted system call. */
155 if (errno == EINTR) continue;
156 exit(1);
157 }
158
159 /* Store available information */
160 CUR_REQ.seqno = 0;
161 CUR_REQ.ip_address = sin.sin_addr.s_addr;
162 CUR_REQ.cl_port = sin.sin_port;
163
164 /* Parse a request packet and save sequence number */
165 if ((status = parse_pkt(packet, pktlen, message))
166 != SUCCESS)
167 {
168 /* If error, format packet to send back to the client */
169 respond(status, (char *)NULL);
170 }
171 else
172 {
173 /* Check for retransmitted packet. handle_retransmitted()
174 returns true if it handled a retransmitted packet. */
175 if (!handle_retransmitted())
176 break;
177 }
178 }
179}
180
181void report(status, message)
182 int status;
183 char * message;
184{
185 respond(status, message);
186}
187
188int format_pkt(packet, pktlenp, seqno, cl_status, message)
189 char *packet; /* Packet buffer */
190 int *pktlenp; /* Pointer to packet size */
191 U_32BIT seqno; /* Sequence number */
192 int cl_status; /* Error status to return to client */
193 char *message; /* Error message to return to client */
194 /* This routine prepares a packet to send back to the client. A
195 non-zero return status means that the client error message was
196 truncated. */
197{
198 int len; /* Amount of message to send */
199 int status = SUCCESS; /* Return status */
200
201 /* Convert byte order to network byte order */
202 U_32BIT vers = htonl((U_32BIT)CUR_UREG_VERSION);
203 cl_status = htonl((U_32BIT)cl_status);
204 /* Put current user registration protocol version into the packet */
205 bcopy((char *)&vers, packet, sizeof(U_32BIT));
206 /* Put sequence number into the packet */
207 bcopy((char *)&seqno, packet+sizeof(U_32BIT), sizeof(U_32BIT));
208 /* Put error status into the packet */
209 bcopy((char *)&cl_status, packet+ 2*sizeof(U_32BIT), sizeof(U_32BIT));
210
211 /* Find out how much of the message to copy; truncate if too short. */
212 /* How much room is there left? */
213 len = *pktlenp - sizeof(U_32BIT)*3;
214 if (len < strlen(message) + 1) /* Room for null terminator */
215 {
216 status = FAILURE; /* Message was truncated */
217 /* Truncate the message */
218 message[len-1] = NULL;
219 }
220
221 /* Copy the message into the packet */
222 (void) strcpy(packet+3*sizeof(U_32BIT), message);
223 *pktlenp = 3*sizeof(U_32BIT) + strlen(message);
224
225 return status;
226}
227
228/* The ureg_validate_char variable and routine were taken verbatim
229 out of server/qsupport.qc where they are called
230 validate_chars. At some point, it may be desirable
231 to put this functionality in one place. */
232
233/* ureg_validate_char: verify that there are no illegal characters in
234 * the string. Legal characters are printing chars other than
235 * ", *, ?, \, [ and ].
236 */
237static int illegalchars[] = {
238 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
239 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
240 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
241 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
242 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
243 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
244 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
245 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
246 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
247 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
248 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
249 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
250 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
251 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
252 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
253 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
254};
255
256ureg_validate_char(s)
257register char *s;
258{
259 while (*s)
260 if (illegalchars[*s++])
261 return(FAILURE);
262 return(SUCCESS);
263}
264
265parse_pkt(packet, pktlen, message)
266 char *packet;
267 int pktlen;
268 struct msg *message;
269 /* This routine checks a packet and puts the information in it in
270 a structure if it is valid. It also saves the sequence number
271 in the list of saved requests. */
272{
273 int status = SUCCESS; /* Error status */
274
275 com_err(whoami,0,"Packet received");
276
277 if (pktlen < sizeof(U_32BIT)) status = UREG_BROKEN_PACKET;
278 if (status == SUCCESS)
279 {
280 /* Extract the user registration protocol version from the packet */
281 bcopy(packet, (char *)&message->version, sizeof(long));
282 /* Convert byte order from network to host */
283 message->version = ntohl(message->version);
284 /* Verify version */
285 if (message->version != CUR_UREG_VERSION)
286 status = UREG_WRONG_VERSION;
287 }
288
289 if (status == SUCCESS)
290 {
291 packet += sizeof(U_32BIT);
292 pktlen -= sizeof(U_32BIT);
293
294 if (pktlen < sizeof(U_32BIT))
295 status = UREG_BROKEN_PACKET;
296 }
297
298 if (status == SUCCESS)
299 {
300 /* Extract the sequence number from the packet */
301 bcopy(packet, (char *)&CUR_REQ.seqno, sizeof(long));
302
303 packet += sizeof(U_32BIT);
304 pktlen -= sizeof(U_32BIT);
305
306 if (pktlen < sizeof(U_32BIT))
307 status = UREG_BROKEN_PACKET;
308 }
309
310 if (status == SUCCESS)
311 {
312 /* Extract the request from the packet */
313 bcopy(packet, (char *)(&message->request), sizeof(U_32BIT));
314 message->request = ntohl(message->request);
315 packet += sizeof(U_32BIT);
316 pktlen -= sizeof(U_32BIT);
317
318 /* Make sure that the packet contains only valid characters up
319 to the next null */
320 if (ureg_validate_char(packet) != SUCCESS)
321 {
322 com_err(whoami,0,"Packet contains invalid characters.");
323 status = UREG_USER_NOT_FOUND;
324 }
325 else
326 {
327 /* Extract first name from the packet */
328 message->first = packet;
329
330 /* Scan forward until null appears in the packet or there
331 is no more packet! */
332 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
333 if (pktlen <= 0)
334 status = UREG_BROKEN_PACKET;
335 }
336 }
337
338 if (status == SUCCESS)
339 {
340 /* Skip over the null */
341 packet++, pktlen--;
342
343 if (ureg_validate_char(packet) != SUCCESS)
344 {
345 com_err(whoami,0,"Packet contains invalid characters.");
346 status = UREG_USER_NOT_FOUND;
347 }
348 else
349 {
350 /* Extract last name from the packet */
351 message->last = packet;
352
353 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
354 if (pktlen <= 0)
355 status = UREG_BROKEN_PACKET;
356 }
357 }
358
359 if (status == SUCCESS)
360 {
361 packet++, pktlen--;
362
363 if (pktlen <= 0)
364 status = UREG_BROKEN_PACKET;
365 }
366
367 /* Extract encrypted information from packet */
368 message->encrypted = packet;
369 message->encrypted_len = pktlen;
370
371 if (status == SUCCESS)
372 {
373#ifdef DEBUG
374 com_err(whoami,status,"%s\n%s%d\n%s%d\n%s%s\n%s%s",
375 "Packet parsed successfully. Packet contains:",
376 " Protocol version: ",message->version,
377 " Request: ",message->request,
378 " First name: ",message->first,
379 " Last name: ",message->last);
380#else /* DEBUG */
381 com_err(whoami,status,"Request %d for %s %s",message->request,
382 message->first,message->last);
383#endif DEBUG
384 }
385 else
386 com_err(whoami,status," - parse packet failed.");
387
388 return status;
389}
390
391/*
392 * Local Variables:
393 * mode: c
394 * c-argdecl-indent: 2
395 * c-brace-offset: -4
396 * c-continued-statement-offset: 4
397 * c-indent-level: 4
398 * c-label-offset: -2
399 * End:
400 */
This page took 0.096802 seconds and 5 git commands to generate.