]> andersk Git - moira.git/blame - reg_svr/requests.c
Solaris/POSIX changes
[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 *
2ce085d2 10 * Server for user registration with Moira and Kerberos.
9a83b251 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>
2ce085d2 37#include "moira.h"
38#include "moira_site.h"
952aa193 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 }
15fa49b5 90 memset(&sin, 0, sizeof(sin));
9a83b251 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 */
15fa49b5 218 memcpy(packet, &vers, sizeof(U_32BIT));
9a83b251 219 /* Put sequence number into the packet */
15fa49b5 220 memcpy(packet+sizeof(U_32BIT), &seqno, sizeof(U_32BIT));
9a83b251 221 /* Put error status into the packet */
15fa49b5 222 memcpy(packet+ 2*sizeof(U_32BIT), &cl_status, sizeof(U_32BIT));
9a83b251 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;
d6f7a3e1 227 if (message == NULL) message = "";
9a83b251 228 if (len < strlen(message) + 1) /* Room for null terminator */
229 {
230 status = FAILURE; /* Message was truncated */
231 /* Truncate the message */
232 message[len-1] = NULL;
233 }
234
235 /* Copy the message into the packet */
236 (void) strcpy(packet+3*sizeof(U_32BIT), message);
237 *pktlenp = 3*sizeof(U_32BIT) + strlen(message);
238
239 return status;
240}
241
242/* The ureg_validate_char variable and routine were taken verbatim
243 out of server/qsupport.qc where they are called
244 validate_chars. At some point, it may be desirable
245 to put this functionality in one place. */
246
247/* ureg_validate_char: verify that there are no illegal characters in
248 * the string. Legal characters are printing chars other than
249 * ", *, ?, \, [ and ].
250 */
251static int illegalchars[] = {
252 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
253 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
254 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
255 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
256 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
257 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
258 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
259 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
268};
269
270ureg_validate_char(s)
271register char *s;
272{
273 while (*s)
274 if (illegalchars[*s++])
275 return(FAILURE);
276 return(SUCCESS);
277}
278
279parse_pkt(packet, pktlen, message)
280 char *packet;
281 int pktlen;
282 struct msg *message;
283 /* This routine checks a packet and puts the information in it in
284 a structure if it is valid. It also saves the sequence number
285 in the list of saved requests. */
286{
287 int status = SUCCESS; /* Error status */
288
289 com_err(whoami,0,"Packet received");
290
291 if (pktlen < sizeof(U_32BIT)) status = UREG_BROKEN_PACKET;
292 if (status == SUCCESS)
293 {
294 /* Extract the user registration protocol version from the packet */
15fa49b5 295 memcpy(&message->version, packet, sizeof(long));
9a83b251 296 /* Convert byte order from network to host */
297 message->version = ntohl(message->version);
298 /* Verify version */
299 if (message->version != CUR_UREG_VERSION)
300 status = UREG_WRONG_VERSION;
301 }
302
303 if (status == SUCCESS)
304 {
305 packet += sizeof(U_32BIT);
306 pktlen -= sizeof(U_32BIT);
307
308 if (pktlen < sizeof(U_32BIT))
309 status = UREG_BROKEN_PACKET;
310 }
311
312 if (status == SUCCESS)
313 {
314 /* Extract the sequence number from the packet */
15fa49b5 315 memcpy(&CUR_REQ.seqno, packet, sizeof(long));
9a83b251 316
317 packet += sizeof(U_32BIT);
318 pktlen -= sizeof(U_32BIT);
319
320 if (pktlen < sizeof(U_32BIT))
321 status = UREG_BROKEN_PACKET;
322 }
323
324 if (status == SUCCESS)
325 {
326 /* Extract the request from the packet */
15fa49b5 327 memcpy(&message->request, packet, sizeof(U_32BIT));
9a83b251 328 message->request = ntohl(message->request);
329 packet += sizeof(U_32BIT);
330 pktlen -= sizeof(U_32BIT);
331
332 /* Make sure that the packet contains only valid characters up
333 to the next null */
334 if (ureg_validate_char(packet) != SUCCESS)
335 {
336 com_err(whoami,0,"Packet contains invalid characters.");
337 status = UREG_USER_NOT_FOUND;
338 }
339 else
340 {
341 /* Extract first name from the packet */
342 message->first = packet;
343
344 /* Scan forward until null appears in the packet or there
345 is no more packet! */
346 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
347 if (pktlen <= 0)
348 status = UREG_BROKEN_PACKET;
349 }
350 }
351
352 if (status == SUCCESS)
353 {
354 /* Skip over the null */
355 packet++, pktlen--;
356
357 if (ureg_validate_char(packet) != SUCCESS)
358 {
359 com_err(whoami,0,"Packet contains invalid characters.");
360 status = UREG_USER_NOT_FOUND;
361 }
362 else
363 {
364 /* Extract last name from the packet */
365 message->last = packet;
366
367 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
368 if (pktlen <= 0)
369 status = UREG_BROKEN_PACKET;
370 }
371 }
372
373 if (status == SUCCESS)
374 {
375 packet++, pktlen--;
376
377 if (pktlen <= 0)
378 status = UREG_BROKEN_PACKET;
379 }
380
381 /* Extract encrypted information from packet */
382 message->encrypted = packet;
383 message->encrypted_len = pktlen;
384
385 if (status == SUCCESS)
386 {
387#ifdef DEBUG
388 com_err(whoami,status,"%s\n%s%d\n%s%d\n%s%s\n%s%s",
389 "Packet parsed successfully. Packet contains:",
390 " Protocol version: ",message->version,
391 " Request: ",message->request,
392 " First name: ",message->first,
393 " Last name: ",message->last);
394#else /* DEBUG */
395 com_err(whoami,status,"Request %d for %s %s",message->request,
396 message->first,message->last);
397#endif DEBUG
398 }
399 else
400 com_err(whoami,status," - parse packet failed.");
401
402 return status;
403}
f3835da8 404
405
406u_long cur_req_sender()
407{
408 return (CUR_REQ.ip_address);
409}
This page took 0.132016 seconds and 5 git commands to generate.