6 * Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
10 * Server for user registration with Moira and Kerberos.
12 * This file handles the processing of requests for the register
17 static char *rcsid_requests_c = "$Header$";
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
25 #include <mit-copyright.h>
29 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
38 #include "moira_site.h"
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)
46 static struct servent *sp; /* Service info from /etc/services */
47 static int s; /* Socket descriptor */
48 static struct sockaddr_in sin; /* Internet style socket address */
49 static int addrlen; /* Size of socket address (sin) */
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. */
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 */
62 static struct request_save requests[NUM_REQUESTS_SAVED]; /* Saved packets */
63 static int cur_request_index = 0; /* Index to the current request */
66 struct request_save *req;
77 /* Get service information from /etc/services */
78 if ((sp = getservbyname("sms_ureg", "udp")) == NULL)
80 com_err(whoami, errno, " unknown service sms_ureg/udp");
84 /* Get an internet style datagram socket */
85 if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
87 com_err(whoami,errno," socket");
90 memset(&sin, 0, sizeof(sin));
92 sin.sin_family = AF_INET;
93 sin.sin_port = sp->s_port;
94 sin.sin_addr.s_addr = INADDR_ANY;
96 /* Bind a name to the socket */
97 if (bind(s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
99 com_err(whoami,errno," bind");
103 for (i = 0; i < NUM_REQUESTS_SAVED; i++)
104 clear_req(&(requests[i]));
107 int handle_retransmitted()
109 register int i; /* A counter */
110 int status = FALSE; /* Return status */
112 for (i = PREV_INDEX(cur_request_index); i != cur_request_index;
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 */
121 com_err(whoami, 0, "Retransmitted packet detected.");
124 (void) sendto(s, requests[i].out_pkt, requests[i].out_pktlen,
125 0, (struct sockaddr *)&sin, addrlen);
133 void 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
141 CUR_REQ.out_pktlen = sizeof(CUR_REQ.out_pkt);
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,
147 (struct sockaddr *)&sin, addrlen);
149 cur_request_index = NEXT_INDEX(cur_request_index);
152 void get_request(message)
153 struct msg *message; /* Will contain formatted packet information */
155 static char packet[BUFSIZ]; /* Buffer for incoming packet */
156 int pktlen; /* Length of incoming packet */
157 int status = FAILURE; /* Error status */
159 /* Sit around waiting for requests from the client. */
162 com_err(whoami, 0, "*** Ready for next request ***");
163 addrlen = sizeof(sin);
164 /* Receive a packet */
165 if ((pktlen = recvfrom(s,packet,sizeof(packet),0,
166 (struct sockaddr *)&sin,&addrlen)) < 0)
168 com_err(whoami, errno, " recvfrom");
169 /* Don't worry if error is interrupted system call. */
170 if (errno == EINTR) continue;
174 /* Store available information */
176 CUR_REQ.ip_address = sin.sin_addr.s_addr;
177 CUR_REQ.cl_port = sin.sin_port;
179 /* Parse a request packet and save sequence number */
180 if ((status = parse_pkt(packet, pktlen, message))
183 /* If error, format packet to send back to the client */
184 respond(status, (char *)NULL);
188 /* Check for retransmitted packet. handle_retransmitted()
189 returns true if it handled a retransmitted packet. */
190 if (!handle_retransmitted())
196 void report(status, message)
200 respond(status, message);
203 int 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
213 int len; /* Amount of message to send */
214 int status = SUCCESS; /* Return status */
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 */
220 memcpy(packet, &vers, sizeof(U_32BIT));
221 /* Put sequence number into the packet */
222 memcpy(packet+sizeof(U_32BIT), &seqno, sizeof(U_32BIT));
223 /* Put error status into the packet */
224 memcpy(packet+ 2*sizeof(U_32BIT), &cl_status, sizeof(U_32BIT));
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;
229 if (message == NULL) message = "";
230 if (len < strlen(message) + 1) /* Room for null terminator */
232 status = FAILURE; /* Message was truncated */
233 /* Truncate the message */
234 message[len-1] = '\0';
237 /* Copy the message into the packet */
238 (void) strcpy(packet+3*sizeof(U_32BIT), message);
239 *pktlenp = 3*sizeof(U_32BIT) + strlen(message);
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. */
249 /* ureg_validate_char: verify that there are no illegal characters in
250 * the string. Legal characters are printing chars other than
251 * ", *, ?, \, [ and ].
253 static 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,
272 ureg_validate_char(s)
276 if (illegalchars[*s++])
281 parse_pkt(packet, pktlen, 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. */
289 int status = SUCCESS; /* Error status */
291 com_err(whoami,0,"Packet received");
293 if (pktlen < sizeof(U_32BIT)) status = UREG_BROKEN_PACKET;
294 if (status == SUCCESS)
296 /* Extract the user registration protocol version from the packet */
297 memcpy(&message->version, packet, sizeof(long));
298 /* Convert byte order from network to host */
299 message->version = ntohl(message->version);
301 if (message->version != CUR_UREG_VERSION)
302 status = UREG_WRONG_VERSION;
305 if (status == SUCCESS)
307 packet += sizeof(U_32BIT);
308 pktlen -= sizeof(U_32BIT);
310 if (pktlen < sizeof(U_32BIT))
311 status = UREG_BROKEN_PACKET;
314 if (status == SUCCESS)
316 /* Extract the sequence number from the packet */
317 memcpy(&CUR_REQ.seqno, packet, sizeof(long));
319 packet += sizeof(U_32BIT);
320 pktlen -= sizeof(U_32BIT);
322 if (pktlen < sizeof(U_32BIT))
323 status = UREG_BROKEN_PACKET;
326 if (status == SUCCESS)
328 /* Extract the request from the packet */
329 memcpy(&message->request, packet, sizeof(U_32BIT));
330 message->request = ntohl(message->request);
331 packet += sizeof(U_32BIT);
332 pktlen -= sizeof(U_32BIT);
334 /* Make sure that the packet contains only valid characters up
336 if (ureg_validate_char(packet) != SUCCESS)
338 com_err(whoami,0,"Packet contains invalid characters.");
339 status = UREG_USER_NOT_FOUND;
343 /* Extract first name from the packet */
344 message->first = packet;
346 /* Scan forward until null appears in the packet or there
347 is no more packet! */
348 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
350 status = UREG_BROKEN_PACKET;
354 if (status == SUCCESS)
356 /* Skip over the null */
359 if (ureg_validate_char(packet) != SUCCESS)
361 com_err(whoami,0,"Packet contains invalid characters.");
362 status = UREG_USER_NOT_FOUND;
366 /* Extract last name from the packet */
367 message->last = packet;
369 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
371 status = UREG_BROKEN_PACKET;
375 if (status == SUCCESS)
380 status = UREG_BROKEN_PACKET;
383 /* Extract encrypted information from packet */
384 message->encrypted = packet;
385 message->encrypted_len = pktlen;
387 if (status == SUCCESS)
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);
397 com_err(whoami,status,"Request %d for %s %s",message->request,
398 message->first,message->last);
402 com_err(whoami,status," - parse packet failed.");
408 u_long cur_req_sender()
410 return (CUR_REQ.ip_address);