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