]> andersk Git - moira.git/blame - reg_svr/requests.c
NULL != ""
[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 */
98a7b0ee 97 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
9a83b251 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,
98a7b0ee 125 0, (struct sockaddr *)&sin, addrlen);
9a83b251 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.");
98a7b0ee 146 (void) sendto(s, CUR_REQ.out_pkt, CUR_REQ.out_pktlen, 0,
147 (struct sockaddr *)&sin, addrlen);
9a83b251 148
149 cur_request_index = NEXT_INDEX(cur_request_index);
150}
151
152void get_request(message)
153 struct msg *message; /* Will contain formatted packet information */
154{
155 static char packet[BUFSIZ]; /* Buffer for incoming packet */
156 int pktlen; /* Length of incoming packet */
157 int status = FAILURE; /* Error status */
158
159 /* Sit around waiting for requests from the client. */
160 for (;;)
161 {
162 com_err(whoami, 0, "*** Ready for next request ***");
163 addrlen = sizeof(sin);
164 /* Receive a packet */
98a7b0ee 165 if ((pktlen = recvfrom(s,packet,sizeof(packet),0,
166 (struct sockaddr *)&sin,&addrlen)) < 0)
9a83b251 167 {
168 com_err(whoami, errno, " recvfrom");
169 /* Don't worry if error is interrupted system call. */
170 if (errno == EINTR) continue;
171 exit(1);
172 }
173
174 /* Store available information */
175 CUR_REQ.seqno = 0;
176 CUR_REQ.ip_address = sin.sin_addr.s_addr;
177 CUR_REQ.cl_port = sin.sin_port;
178
179 /* Parse a request packet and save sequence number */
180 if ((status = parse_pkt(packet, pktlen, message))
181 != SUCCESS)
182 {
183 /* If error, format packet to send back to the client */
184 respond(status, (char *)NULL);
185 }
186 else
187 {
188 /* Check for retransmitted packet. handle_retransmitted()
189 returns true if it handled a retransmitted packet. */
190 if (!handle_retransmitted())
191 break;
192 }
193 }
194}
195
196void report(status, message)
197 int status;
198 char * message;
199{
200 respond(status, message);
201}
202
203int format_pkt(packet, pktlenp, seqno, cl_status, message)
204 char *packet; /* Packet buffer */
205 int *pktlenp; /* Pointer to packet size */
206 U_32BIT seqno; /* Sequence number */
207 int cl_status; /* Error status to return to client */
208 char *message; /* Error message to return to client */
209 /* This routine prepares a packet to send back to the client. A
210 non-zero return status means that the client error message was
211 truncated. */
212{
213 int len; /* Amount of message to send */
214 int status = SUCCESS; /* Return status */
215
216 /* Convert byte order to network byte order */
217 U_32BIT vers = htonl((U_32BIT)CUR_UREG_VERSION);
218 cl_status = htonl((U_32BIT)cl_status);
219 /* Put current user registration protocol version into the packet */
15fa49b5 220 memcpy(packet, &vers, sizeof(U_32BIT));
9a83b251 221 /* Put sequence number into the packet */
15fa49b5 222 memcpy(packet+sizeof(U_32BIT), &seqno, sizeof(U_32BIT));
9a83b251 223 /* Put error status into the packet */
15fa49b5 224 memcpy(packet+ 2*sizeof(U_32BIT), &cl_status, sizeof(U_32BIT));
9a83b251 225
226 /* Find out how much of the message to copy; truncate if too short. */
227 /* How much room is there left? */
228 len = *pktlenp - sizeof(U_32BIT)*3;
d6f7a3e1 229 if (message == NULL) message = "";
9a83b251 230 if (len < strlen(message) + 1) /* Room for null terminator */
231 {
232 status = FAILURE; /* Message was truncated */
233 /* Truncate the message */
16e5277e 234 message[len-1] = '\0';
9a83b251 235 }
236
237 /* Copy the message into the packet */
238 (void) strcpy(packet+3*sizeof(U_32BIT), message);
239 *pktlenp = 3*sizeof(U_32BIT) + strlen(message);
240
241 return status;
242}
243
244/* The ureg_validate_char variable and routine were taken verbatim
245 out of server/qsupport.qc where they are called
246 validate_chars. At some point, it may be desirable
247 to put this functionality in one place. */
248
249/* ureg_validate_char: verify that there are no illegal characters in
250 * the string. Legal characters are printing chars other than
251 * ", *, ?, \, [ and ].
252 */
253static int illegalchars[] = {
254 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
255 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
256 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
257 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
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, 1, 1, 1, 0, 0, /* P - _ */
260 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
261 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
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 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
269 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
270};
271
272ureg_validate_char(s)
273register char *s;
274{
275 while (*s)
276 if (illegalchars[*s++])
277 return(FAILURE);
278 return(SUCCESS);
279}
280
281parse_pkt(packet, pktlen, message)
282 char *packet;
283 int pktlen;
284 struct msg *message;
285 /* This routine checks a packet and puts the information in it in
286 a structure if it is valid. It also saves the sequence number
287 in the list of saved requests. */
288{
289 int status = SUCCESS; /* Error status */
290
291 com_err(whoami,0,"Packet received");
292
293 if (pktlen < sizeof(U_32BIT)) status = UREG_BROKEN_PACKET;
294 if (status == SUCCESS)
295 {
296 /* Extract the user registration protocol version from the packet */
15fa49b5 297 memcpy(&message->version, packet, sizeof(long));
9a83b251 298 /* Convert byte order from network to host */
299 message->version = ntohl(message->version);
300 /* Verify version */
301 if (message->version != CUR_UREG_VERSION)
302 status = UREG_WRONG_VERSION;
303 }
304
305 if (status == SUCCESS)
306 {
307 packet += sizeof(U_32BIT);
308 pktlen -= sizeof(U_32BIT);
309
310 if (pktlen < sizeof(U_32BIT))
311 status = UREG_BROKEN_PACKET;
312 }
313
314 if (status == SUCCESS)
315 {
316 /* Extract the sequence number from the packet */
15fa49b5 317 memcpy(&CUR_REQ.seqno, packet, sizeof(long));
9a83b251 318
319 packet += sizeof(U_32BIT);
320 pktlen -= sizeof(U_32BIT);
321
322 if (pktlen < sizeof(U_32BIT))
323 status = UREG_BROKEN_PACKET;
324 }
325
326 if (status == SUCCESS)
327 {
328 /* Extract the request from the packet */
15fa49b5 329 memcpy(&message->request, packet, sizeof(U_32BIT));
9a83b251 330 message->request = ntohl(message->request);
331 packet += sizeof(U_32BIT);
332 pktlen -= sizeof(U_32BIT);
333
334 /* Make sure that the packet contains only valid characters up
335 to the next null */
336 if (ureg_validate_char(packet) != SUCCESS)
337 {
338 com_err(whoami,0,"Packet contains invalid characters.");
339 status = UREG_USER_NOT_FOUND;
340 }
341 else
342 {
343 /* Extract first name from the packet */
344 message->first = packet;
345
346 /* Scan forward until null appears in the packet or there
347 is no more packet! */
348 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
349 if (pktlen <= 0)
350 status = UREG_BROKEN_PACKET;
351 }
352 }
353
354 if (status == SUCCESS)
355 {
356 /* Skip over the null */
357 packet++, pktlen--;
358
359 if (ureg_validate_char(packet) != SUCCESS)
360 {
361 com_err(whoami,0,"Packet contains invalid characters.");
362 status = UREG_USER_NOT_FOUND;
363 }
364 else
365 {
366 /* Extract last name from the packet */
367 message->last = packet;
368
369 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
370 if (pktlen <= 0)
371 status = UREG_BROKEN_PACKET;
372 }
373 }
374
375 if (status == SUCCESS)
376 {
377 packet++, pktlen--;
378
379 if (pktlen <= 0)
380 status = UREG_BROKEN_PACKET;
381 }
382
383 /* Extract encrypted information from packet */
384 message->encrypted = packet;
385 message->encrypted_len = pktlen;
386
387 if (status == SUCCESS)
388 {
389#ifdef DEBUG
390 com_err(whoami,status,"%s\n%s%d\n%s%d\n%s%s\n%s%s",
391 "Packet parsed successfully. Packet contains:",
392 " Protocol version: ",message->version,
393 " Request: ",message->request,
394 " First name: ",message->first,
395 " Last name: ",message->last);
396#else /* DEBUG */
397 com_err(whoami,status,"Request %d for %s %s",message->request,
398 message->first,message->last);
399#endif DEBUG
400 }
401 else
402 com_err(whoami,status," - parse packet failed.");
403
404 return status;
405}
f3835da8 406
407
408u_long cur_req_sender()
409{
410 return (CUR_REQ.ip_address);
411}
This page took 0.749201 seconds and 5 git commands to generate.