6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
8 * Server for user registration with SMS and Kerberos.
10 * This file handles the processing of requests for the register
15 static char *rcsid_requests_c = "$Header$";
19 * Before you add anything to the list of things that are #included and
20 * #defined, make sure that it is not already done in reg_svr.h
24 #include <sys/socket.h>
25 #include <netinet/in.h>
28 #define NUM_REQUESTS_SAVED 100 /* Number of transactions to save */
29 #define CUR_REQ (requests[cur_request_index]) /* The current request */
30 #define NEXT_INDEX(x) (x == NUM_REQUESTS_SAVED - 1) ? 0 : (x + 1)
31 #define PREV_INDEX(x) (x == 0) ? (NUM_REQUESTS_SAVED - 1) : (x - 1)
33 static struct servent *sp; /* Service info from /etc/services */
34 static int s; /* Socket descriptor */
35 static struct sockaddr_in sin; /* Internet style socket address */
36 static int addrlen; /* Size of socket address (sin) */
38 /* In order to elegantly handle multiple retransmissions, an instance
39 of this structure will be retained for the last NUM_REQUESTS_SAVED
40 transactions with the client. */
42 char out_pkt[BUFSIZ]; /* Buffer for outgoing packet */
43 int out_pktlen; /* Length of outgoing packet */
44 U_32BIT seqno; /* Sequence number for packet transmission */
45 u_long ip_address; /* Internet address of client host */
46 u_short cl_port; /* Port number client used */
49 static struct request_save requests[NUM_REQUESTS_SAVED]; /* Saved packets */
50 static int cur_request_index = 0; /* Index to the current request */
53 struct request_save *req;
64 /* Get service information from /etc/services */
65 if ((sp = getservbyname("sms_ureg", "udp")) == NULL)
67 com_err(whoami, errno, " unknown service sms_ureg/udp");
71 /* Get an internet style datagram socket */
72 if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
74 com_err(whoami,errno," socket");
77 bzero((char *)&sin,(int)sizeof(sin));
79 sin.sin_family = AF_INET;
80 sin.sin_port = sp->s_port;
81 sin.sin_addr.s_addr = INADDR_ANY;
83 /* Bind a name to the socket */
84 if (bind(s, &sin, sizeof(sin)) < 0)
86 com_err(whoami,errno," bind");
90 for (i = 0; i < NUM_REQUESTS_SAVED; i++)
91 clear_req(&(requests[i]));
94 int handle_retransmitted()
96 register int i; /* A counter */
97 int status = FALSE; /* Return status */
99 for (i = PREV_INDEX(cur_request_index); i != cur_request_index;
102 if ((requests[i].seqno == CUR_REQ.seqno) &&
103 (requests[i].ip_address == sin.sin_addr.s_addr) &&
104 (requests[i].cl_port == sin.sin_port))
105 /* This is a retransmitted packet */
108 com_err(whoami, 0, "Retransmitted packet detected.");
111 (void) sendto(s, requests[i].out_pkt, requests[i].out_pktlen,
120 void respond(status,text)
121 int status; /* Return status for the client */
122 char *text; /* Text for the client */
123 /* This routine takes care of sending packets back to the client and
124 caching the necessary information for retransmission detection.
125 It is the only place in which cur_request_index should be
128 CUR_REQ.out_pktlen = sizeof(CUR_REQ.out_pkt);
130 if (format_pkt(CUR_REQ.out_pkt, &(CUR_REQ.out_pktlen),
131 CUR_REQ.seqno, status, text))
132 com_err(whoami,0,"Client error message was truncated.");
133 (void) sendto(s, CUR_REQ.out_pkt, CUR_REQ.out_pktlen, 0, &sin, addrlen);
135 cur_request_index = NEXT_INDEX(cur_request_index);
138 void get_request(message)
139 struct msg *message; /* Will contain formatted packet information */
141 static char packet[BUFSIZ]; /* Buffer for incoming packet */
142 int pktlen; /* Length of incoming packet */
143 int status = FAILURE; /* Error status */
145 /* Sit around waiting for requests from the client. */
148 com_err(whoami, 0, "*** Ready for next request ***");
149 addrlen = sizeof(sin);
150 /* Receive a packet */
151 if ((pktlen = recvfrom(s,packet,sizeof(packet),0,&sin,&addrlen)) < 0)
153 com_err(whoami, errno, " recvfrom");
154 /* Don't worry if error is interrupted system call. */
155 if (errno == EINTR) continue;
159 /* Store available information */
161 CUR_REQ.ip_address = sin.sin_addr.s_addr;
162 CUR_REQ.cl_port = sin.sin_port;
164 /* Parse a request packet and save sequence number */
165 if ((status = parse_pkt(packet, pktlen, message))
168 /* If error, format packet to send back to the client */
169 respond(status, (char *)NULL);
173 /* Check for retransmitted packet. handle_retransmitted()
174 returns true if it handled a retransmitted packet. */
175 if (!handle_retransmitted())
181 void report(status, message)
185 respond(status, message);
188 int format_pkt(packet, pktlenp, seqno, cl_status, message)
189 char *packet; /* Packet buffer */
190 int *pktlenp; /* Pointer to packet size */
191 U_32BIT seqno; /* Sequence number */
192 int cl_status; /* Error status to return to client */
193 char *message; /* Error message to return to client */
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
198 int len; /* Amount of message to send */
199 int status = SUCCESS; /* Return status */
201 /* Convert byte order to network byte order */
202 U_32BIT vers = htonl((U_32BIT)CUR_UREG_VERSION);
203 cl_status = htonl((U_32BIT)cl_status);
204 /* Put current user registration protocol version into the packet */
205 bcopy((char *)&vers, packet, sizeof(U_32BIT));
206 /* Put sequence number into the packet */
207 bcopy((char *)&seqno, packet+sizeof(U_32BIT), sizeof(U_32BIT));
208 /* Put error status into the packet */
209 bcopy((char *)&cl_status, packet+ 2*sizeof(U_32BIT), sizeof(U_32BIT));
211 /* Find out how much of the message to copy; truncate if too short. */
212 /* How much room is there left? */
213 len = *pktlenp - sizeof(U_32BIT)*3;
214 if (len < strlen(message) + 1) /* Room for null terminator */
216 status = FAILURE; /* Message was truncated */
217 /* Truncate the message */
218 message[len-1] = NULL;
221 /* Copy the message into the packet */
222 (void) strcpy(packet+3*sizeof(U_32BIT), message);
223 *pktlenp = 3*sizeof(U_32BIT) + strlen(message);
228 /* The ureg_validate_char variable and routine were taken verbatim
229 out of server/qsupport.qc where they are called
230 validate_chars. At some point, it may be desirable
231 to put this functionality in one place. */
233 /* ureg_validate_char: verify that there are no illegal characters in
234 * the string. Legal characters are printing chars other than
235 * ", *, ?, \, [ and ].
237 static int illegalchars[] = {
238 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
239 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
240 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, /* SPACE - / */
241 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* 0 - ? */
242 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* @ - O */
243 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, /* P - _ */
244 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
245 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, /* p - ^? */
246 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
247 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
248 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
249 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
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,
256 ureg_validate_char(s)
260 if (illegalchars[*s++])
265 parse_pkt(packet, pktlen, message)
269 /* This routine checks a packet and puts the information in it in
270 a structure if it is valid. It also saves the sequence number
271 in the list of saved requests. */
273 int status = SUCCESS; /* Error status */
275 com_err(whoami,0,"Packet received");
277 if (pktlen < sizeof(U_32BIT)) status = UREG_BROKEN_PACKET;
278 if (status == SUCCESS)
280 /* Extract the user registration protocol version from the packet */
281 bcopy(packet, (char *)&message->version, sizeof(long));
282 /* Convert byte order from network to host */
283 message->version = ntohl(message->version);
285 if (message->version != CUR_UREG_VERSION)
286 status = UREG_WRONG_VERSION;
289 if (status == SUCCESS)
291 packet += sizeof(U_32BIT);
292 pktlen -= sizeof(U_32BIT);
294 if (pktlen < sizeof(U_32BIT))
295 status = UREG_BROKEN_PACKET;
298 if (status == SUCCESS)
300 /* Extract the sequence number from the packet */
301 bcopy(packet, (char *)&CUR_REQ.seqno, sizeof(long));
303 packet += sizeof(U_32BIT);
304 pktlen -= sizeof(U_32BIT);
306 if (pktlen < sizeof(U_32BIT))
307 status = UREG_BROKEN_PACKET;
310 if (status == SUCCESS)
312 /* Extract the request from the packet */
313 bcopy(packet, (char *)(&message->request), sizeof(U_32BIT));
314 message->request = ntohl(message->request);
315 packet += sizeof(U_32BIT);
316 pktlen -= sizeof(U_32BIT);
318 /* Make sure that the packet contains only valid characters up
320 if (ureg_validate_char(packet) != SUCCESS)
322 com_err(whoami,0,"Packet contains invalid characters.");
323 status = UREG_USER_NOT_FOUND;
327 /* Extract first name from the packet */
328 message->first = packet;
330 /* Scan forward until null appears in the packet or there
331 is no more packet! */
332 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
334 status = UREG_BROKEN_PACKET;
338 if (status == SUCCESS)
340 /* Skip over the null */
343 if (ureg_validate_char(packet) != SUCCESS)
345 com_err(whoami,0,"Packet contains invalid characters.");
346 status = UREG_USER_NOT_FOUND;
350 /* Extract last name from the packet */
351 message->last = packet;
353 for (; *packet && pktlen > 0; --pktlen, ++packet) continue;
355 status = UREG_BROKEN_PACKET;
359 if (status == SUCCESS)
364 status = UREG_BROKEN_PACKET;
367 /* Extract encrypted information from packet */
368 message->encrypted = packet;
369 message->encrypted_len = pktlen;
371 if (status == SUCCESS)
374 com_err(whoami,status,"%s\n%s%d\n%s%d\n%s%s\n%s%s",
375 "Packet parsed successfully. Packet contains:",
376 " Protocol version: ",message->version,
377 " Request: ",message->request,
378 " First name: ",message->first,
379 " Last name: ",message->last);
381 com_err(whoami,status,"Request %d for %s %s",message->request,
382 message->first,message->last);
386 com_err(whoami,status," - parse packet failed.");
394 * c-argdecl-indent: 2
396 * c-continued-statement-offset: 4