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