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