]> andersk Git - moira.git/blame - reg_svr/requests.c
Change `SMS' to `Moira' where possible.
[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
5eaef520 22 * #defined, make sure that it is not already done in reg_svr.h
9a83b251 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)
5eaef520 45
9a83b251 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) */
5eaef520 50
51/* In order to elegantly handle multiple retransmissions, an instance
9a83b251 52 of this structure will be retained for the last NUM_REQUESTS_SAVED
53 transactions with the client. */
54struct request_save {
5eaef520 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 */
9a83b251 60};
61
62static struct request_save requests[NUM_REQUESTS_SAVED]; /* Saved packets */
63static int cur_request_index = 0; /* Index to the current request */
64
5eaef520 65void clear_req(struct request_save *req)
9a83b251 66{
5eaef520 67 req->seqno = 0;
68 req->ip_address = 0;
69 req->cl_port = 0;
9a83b251 70}
71
5eaef520 72void req_initialize(void)
9a83b251 73{
44d12d58 74 int i;
9a83b251 75
5eaef520 76 /* Get service information from /etc/services */
59ec8dae 77 if (!(sp = getservbyname("moira_ureg", "udp")))
9a83b251 78 {
59ec8dae 79 com_err(whoami, errno, " unknown service moira_ureg/udp");
5eaef520 80 exit(1);
9a83b251 81 }
5eaef520 82
83 /* Get an internet style datagram socket */
84 if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
9a83b251 85 {
5eaef520 86 com_err(whoami, errno, " socket");
87 exit(1);
9a83b251 88 }
5eaef520 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)
9a83b251 97 {
5eaef520 98 com_err(whoami, errno, " bind");
99 exit(1);
9a83b251 100 }
101
5eaef520 102 for (i = 0; i < NUM_REQUESTS_SAVED; i++)
103 clear_req(&(requests[i]));
104}
9a83b251 105
5eaef520 106int handle_retransmitted(void)
9a83b251 107{
44d12d58 108 int i; /* A counter */
5eaef520 109 int status = FALSE; /* Return status */
110
111 for (i = PREV_INDEX(cur_request_index); i != cur_request_index;
112 i = PREV_INDEX(i))
9a83b251 113 {
5eaef520 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 */
9a83b251 118 {
5eaef520 119 status = TRUE;
120 sendto(s, requests[i].out_pkt, requests[i].out_pktlen,
121 0, (struct sockaddr *)&sin, addrlen);
122 break;
9a83b251 123 }
124 }
125
5eaef520 126 return status;
9a83b251 127}
128
5eaef520 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)
9a83b251 134{
5eaef520 135 CUR_REQ.out_pktlen = sizeof(CUR_REQ.out_pkt);
9a83b251 136
5eaef520 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);
9a83b251 142
5eaef520 143 cur_request_index = NEXT_INDEX(cur_request_index);
9a83b251 144}
145
5eaef520 146void get_request(struct msg *message)
9a83b251 147{
5eaef520 148 static char packet[BUFSIZ]; /* Buffer for incoming packet */
149 int pktlen; /* Length of incoming packet */
150 int status = FAILURE; /* Error status */
9a83b251 151
5eaef520 152 /* Sit around waiting for requests from the client. */
153 for (;;)
9a83b251 154 {
5eaef520 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)
9a83b251 160 {
5eaef520 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);
9a83b251 166 }
5eaef520 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)
9a83b251 175 {
5eaef520 176 /* If error, format packet to send back to the client */
177 respond(status, NULL);
9a83b251 178 }
5eaef520 179 else
9a83b251 180 {
5eaef520 181 /* Check for retransmitted packet. handle_retransmitted()
182 returns true if it handled a retransmitted packet. */
183 if (!handle_retransmitted())
184 break;
9a83b251 185 }
186 }
187}
188
5eaef520 189void report(int status, char *message)
9a83b251 190{
5eaef520 191 respond(status, message);
9a83b251 192}
193
5eaef520 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)
9a83b251 199{
5eaef520 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 */
9a83b251 219 {
5eaef520 220 status = FAILURE; /* Message was truncated */
221 /* Truncate the message */
222 message[len - 1] = '\0';
9a83b251 223 }
224
5eaef520 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;
9a83b251 230}
231
5eaef520 232/* The ureg_validate_char variable and routine were taken verbatim
9a83b251 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
5eaef520 238 * the string. Legal characters are printing chars other than
9a83b251 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
44d12d58 260int ureg_validate_char(char *s)
9a83b251 261{
5eaef520 262 while (*s)
263 {
9a83b251 264 if (illegalchars[*s++])
5eaef520 265 return FAILURE;
266 }
267 return SUCCESS;
9a83b251 268}
269
5eaef520 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)
9a83b251 274{
5eaef520 275 int status = SUCCESS; /* Error status */
9a83b251 276
5eaef520 277 com_err(whoami, 0, "Packet received");
9a83b251 278
5eaef520 279 if (pktlen < sizeof(U_32BIT))
280 status = UREG_BROKEN_PACKET;
281 if (status == SUCCESS)
9a83b251 282 {
5eaef520 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;
9a83b251 290 }
291
5eaef520 292 if (status == SUCCESS)
9a83b251 293 {
5eaef520 294 packet += sizeof(U_32BIT);
295 pktlen -= sizeof(U_32BIT);
296
297 if (pktlen < sizeof(U_32BIT))
298 status = UREG_BROKEN_PACKET;
9a83b251 299 }
300
5eaef520 301 if (status == SUCCESS)
9a83b251 302 {
5eaef520 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;
9a83b251 311 }
312
5eaef520 313 if (status == SUCCESS)
9a83b251 314 {
5eaef520 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)
9a83b251 324 {
5eaef520 325 com_err(whoami, 0, "Packet contains invalid characters.");
326 status = UREG_USER_NOT_FOUND;
9a83b251 327 }
5eaef520 328 else
9a83b251 329 {
5eaef520 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;
9a83b251 339 }
340 }
5eaef520 341
342 if (status == SUCCESS)
9a83b251 343 {
5eaef520 344 /* Skip over the null */
345 packet++, pktlen--;
346
347 if (ureg_validate_char(packet) != SUCCESS)
9a83b251 348 {
5eaef520 349 com_err(whoami, 0, "Packet contains invalid characters.");
350 status = UREG_USER_NOT_FOUND;
9a83b251 351 }
5eaef520 352 else
9a83b251 353 {
5eaef520 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;
9a83b251 361 }
362 }
363
5eaef520 364 if (status == SUCCESS)
9a83b251 365 {
5eaef520 366 packet++, pktlen--;
367
368 if (pktlen <= 0)
369 status = UREG_BROKEN_PACKET;
9a83b251 370 }
371
5eaef520 372 /* Extract encrypted information from packet */
373 message->encrypted = packet;
374 message->encrypted_len = pktlen;
375
376 if (status == SUCCESS)
9a83b251 377 {
5eaef520 378 com_err(whoami, status, "Request %d for %s %s", message->request,
379 message->first, message->last);
9a83b251 380 }
5eaef520 381 else
382 com_err(whoami, status, " - parse packet failed.");
9a83b251 383
5eaef520 384 return status;
9a83b251 385}
f3835da8 386
387
5eaef520 388u_long cur_req_sender(void)
f3835da8 389{
5eaef520 390 return CUR_REQ.ip_address;
f3835da8 391}
This page took 0.139609 seconds and 5 git commands to generate.