]> andersk Git - moira.git/blame_incremental - reg_svr/requests.c
Code style cleanup. (No functional changes)
[moira.git] / reg_svr / requests.c
... / ...
CommitLineData
1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
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>.
9 *
10 * Server for user registration with Moira 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
25#include <mit-copyright.h>
26#include <stdio.h>
27#include <strings.h>
28#include <ctype.h>
29#include <sys/types.h>
30#include <sys/file.h>
31#include <krb.h>
32#include <des.h>
33#include <errno.h>
34#include <sys/socket.h>
35#include <netinet/in.h>
36#include <netdb.h>
37#include "moira.h"
38#include "moira_site.h"
39#include "reg_svr.h"
40
41#define NUM_REQUESTS_SAVED 100 /* Number of transactions to save */
42#define CUR_REQ (requests[cur_request_index]) /* The current request */
43#define NEXT_INDEX(x) (x == NUM_REQUESTS_SAVED - 1) ? 0 : (x + 1)
44#define PREV_INDEX(x) (x == 0) ? (NUM_REQUESTS_SAVED - 1) : (x - 1)
45
46static struct servent *sp; /* Service info from /etc/services */
47static int s; /* Socket descriptor */
48static struct sockaddr_in sin; /* Internet style socket address */
49static int addrlen; /* Size of socket address (sin) */
50
51/* In order to elegantly handle multiple retransmissions, an instance
52 of this structure will be retained for the last NUM_REQUESTS_SAVED
53 transactions with the client. */
54struct request_save {
55 char out_pkt[BUFSIZ]; /* Buffer for outgoing packet */
56 int out_pktlen; /* Length of outgoing packet */
57 U_32BIT seqno; /* Sequence number for packet transmission */
58 u_long ip_address; /* Internet address of client host */
59 u_short cl_port; /* Port number client used */
60};
61
62static struct request_save requests[NUM_REQUESTS_SAVED]; /* Saved packets */
63static int cur_request_index = 0; /* Index to the current request */
64
65void clear_req(struct request_save *req)
66{
67 req->seqno = 0;
68 req->ip_address = 0;
69 req->cl_port = 0;
70}
71
72void req_initialize(void)
73{
74 register int i;
75
76 /* Get service information from /etc/services */
77 if (!(sp = getservbyname("sms_ureg", "udp")))
78 {
79 com_err(whoami, errno, " unknown service sms_ureg/udp");
80 exit(1);
81 }
82
83 /* Get an internet style datagram socket */
84 if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
85 {
86 com_err(whoami, errno, " socket");
87 exit(1);
88 }
89 memset(&sin, 0, sizeof(sin));
90
91 sin.sin_family = AF_INET;
92 sin.sin_port = sp->s_port;
93 sin.sin_addr.s_addr = INADDR_ANY;
94
95 /* Bind a name to the socket */
96 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
97 {
98 com_err(whoami, errno, " bind");
99 exit(1);
100 }
101
102 for (i = 0; i < NUM_REQUESTS_SAVED; i++)
103 clear_req(&(requests[i]));
104}
105
106int handle_retransmitted(void)
107{
108 register int i; /* A counter */
109 int status = FALSE; /* Return status */
110
111 for (i = PREV_INDEX(cur_request_index); i != cur_request_index;
112 i = PREV_INDEX(i))
113 {
114 if ((requests[i].seqno == CUR_REQ.seqno) &&
115 (requests[i].ip_address == sin.sin_addr.s_addr) &&
116 (requests[i].cl_port == sin.sin_port))
117 /* This is a retransmitted packet */
118 {
119 status = TRUE;
120 sendto(s, requests[i].out_pkt, requests[i].out_pktlen,
121 0, (struct sockaddr *)&sin, addrlen);
122 break;
123 }
124 }
125
126 return status;
127}
128
129/* This routine takes care of sending packets back to the client and
130 caching the necessary information for retransmission detection.
131 It is the only place in which cur_request_index should be
132 changed. */
133void respond(int status, char *text)
134{
135 CUR_REQ.out_pktlen = sizeof(CUR_REQ.out_pkt);
136
137 if (format_pkt(CUR_REQ.out_pkt, &(CUR_REQ.out_pktlen),
138 CUR_REQ.seqno, status, text))
139 com_err(whoami, 0, "Client error message was truncated.");
140 sendto(s, CUR_REQ.out_pkt, CUR_REQ.out_pktlen, 0,
141 (struct sockaddr *)&sin, addrlen);
142
143 cur_request_index = NEXT_INDEX(cur_request_index);
144}
145
146void get_request(struct msg *message)
147{
148 static char packet[BUFSIZ]; /* Buffer for incoming packet */
149 int pktlen; /* Length of incoming packet */
150 int status = FAILURE; /* Error status */
151
152 /* Sit around waiting for requests from the client. */
153 for (;;)
154 {
155 com_err(whoami, 0, "*** Ready for next request ***");
156 addrlen = sizeof(sin);
157 /* Receive a packet */
158 if ((pktlen = recvfrom(s, packet, sizeof(packet), 0,
159 (struct sockaddr *)&sin, &addrlen)) < 0)
160 {
161 com_err(whoami, errno, " recvfrom");
162 /* Don't worry if error is interrupted system call. */
163 if (errno == EINTR)
164 continue;
165 exit(1);
166 }
167
168 /* Store available information */
169 CUR_REQ.seqno = 0;
170 CUR_REQ.ip_address = sin.sin_addr.s_addr;
171 CUR_REQ.cl_port = sin.sin_port;
172
173 /* Parse a request packet and save sequence number */
174 if ((status = parse_pkt(packet, pktlen, message)) != SUCCESS)
175 {
176 /* If error, format packet to send back to the client */
177 respond(status, NULL);
178 }
179 else
180 {
181 /* Check for retransmitted packet. handle_retransmitted()
182 returns true if it handled a retransmitted packet. */
183 if (!handle_retransmitted())
184 break;
185 }
186 }
187}
188
189void report(int status, char *message)
190{
191 respond(status, message);
192}
193
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. */
197int format_pkt(char *packet, int *pktlenp, U_32BIT seqno,
198 int cl_status, char *message)
199{
200 int len; /* Amount of message to send */
201 int status = SUCCESS; /* Return status */
202
203 /* Convert byte order to network byte order */
204 U_32BIT vers = htonl((U_32BIT)CUR_UREG_VERSION);
205 cl_status = htonl((U_32BIT)cl_status);
206 /* Put current user registration protocol version into the packet */
207 memcpy(packet, &vers, sizeof(U_32BIT));
208 /* Put sequence number into the packet */
209 memcpy(packet + sizeof(U_32BIT), &seqno, sizeof(U_32BIT));
210 /* Put error status into the packet */
211 memcpy(packet + 2 * sizeof(U_32BIT), &cl_status, sizeof(U_32BIT));
212
213 /* Find out how much of the message to copy; truncate if too short. */
214 /* How much room is there left? */
215 len = *pktlenp - sizeof(U_32BIT) * 3;
216 if (!message)
217 message = "";
218 if (len < strlen(message) + 1) /* Room for null terminator */
219 {
220 status = FAILURE; /* Message was truncated */
221 /* Truncate the message */
222 message[len - 1] = '\0';
223 }
224
225 /* Copy the message into the packet */
226 strcpy(packet + 3 * sizeof(U_32BIT), message);
227 *pktlenp = 3 * sizeof(U_32BIT) + strlen(message);
228
229 return status;
230}
231
232/* The ureg_validate_char variable and routine were taken verbatim
233 out of server/qsupport.qc where they are called
234 validate_chars. At some point, it may be desirable
235 to put this functionality in one place. */
236
237/* ureg_validate_char: verify that there are no illegal characters in
238 * the string. Legal characters are printing chars other than
239 * ", *, ?, \, [ and ].
240 */
241static int illegalchars[] = {
242 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
243 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
244 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
245 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
246 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
247 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
248 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
258};
259
260int ureg_validate_char(register char *s)
261{
262 while (*s)
263 {
264 if (illegalchars[*s++])
265 return FAILURE;
266 }
267 return SUCCESS;
268}
269
270/* This routine checks a packet and puts the information in it in
271 a structure if it is valid. It also saves the sequence number
272 in the list of saved requests. */
273int parse_pkt(char *packet, int pktlen, struct msg *message)
274{
275 int status = SUCCESS; /* Error status */
276
277 com_err(whoami, 0, "Packet received");
278
279 if (pktlen < sizeof(U_32BIT))
280 status = UREG_BROKEN_PACKET;
281 if (status == SUCCESS)
282 {
283 /* Extract the user registration protocol version from the packet */
284 memcpy(&message->version, packet, 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 memcpy(&CUR_REQ.seqno, packet, 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 memcpy(&message->request, packet, 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)
336 continue;
337 if (pktlen <= 0)
338 status = UREG_BROKEN_PACKET;
339 }
340 }
341
342 if (status == SUCCESS)
343 {
344 /* Skip over the null */
345 packet++, pktlen--;
346
347 if (ureg_validate_char(packet) != SUCCESS)
348 {
349 com_err(whoami, 0, "Packet contains invalid characters.");
350 status = UREG_USER_NOT_FOUND;
351 }
352 else
353 {
354 /* Extract last name from the packet */
355 message->last = packet;
356
357 for (; *packet && pktlen > 0; --pktlen, ++packet)
358 continue;
359 if (pktlen <= 0)
360 status = UREG_BROKEN_PACKET;
361 }
362 }
363
364 if (status == SUCCESS)
365 {
366 packet++, pktlen--;
367
368 if (pktlen <= 0)
369 status = UREG_BROKEN_PACKET;
370 }
371
372 /* Extract encrypted information from packet */
373 message->encrypted = packet;
374 message->encrypted_len = pktlen;
375
376 if (status == SUCCESS)
377 {
378 com_err(whoami, status, "Request %d for %s %s", message->request,
379 message->first, message->last);
380 }
381 else
382 com_err(whoami, status, " - parse packet failed.");
383
384 return status;
385}
386
387
388u_long cur_req_sender(void)
389{
390 return CUR_REQ.ip_address;
391}
This page took 0.046901 seconds and 5 git commands to generate.