]> andersk Git - moira.git/blob - reg_svr/requests.c
Code style cleanup. (No functional changes)
[moira.git] / reg_svr / requests.c
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
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>.
9  *
10  *      Server for user registration with Moira and Kerberos.
11  *
12  *      This file handles the processing of requests for the register
13  *      server.
14  */
15
16 #ifndef lint
17 static 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
25 #include <mit-copyright.h>
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>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36 #include <netdb.h>
37 #include "moira.h"
38 #include "moira_site.h"
39 #include "reg_svr.h"
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
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) */
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. */
54 struct 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
62 static struct request_save requests[NUM_REQUESTS_SAVED]; /* Saved packets */
63 static int cur_request_index = 0;       /* Index to the current request */
64
65 void clear_req(struct request_save *req)
66 {
67   req->seqno = 0;
68   req->ip_address = 0;
69   req->cl_port = 0;
70 }
71
72 void req_initialize(void)
73 {
74   register int i;
75
76   /* Get service information from /etc/services */
77   if (!(sp = getservbyname("sms_ureg", "udp")))
78     {
79       com_err(whoami, errno, " unknown service sms_ureg/udp");
80       exit(1);
81     }
82
83   /* Get an internet style datagram socket */
84   if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0)
85     {
86       com_err(whoami, errno, " socket");
87       exit(1);
88     }
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)
97     {
98       com_err(whoami, errno, " bind");
99       exit(1);
100     }
101
102   for (i = 0; i < NUM_REQUESTS_SAVED; i++)
103     clear_req(&(requests[i]));
104 }
105
106 int handle_retransmitted(void)
107 {
108   register int i;               /* A counter */
109   int status = FALSE;           /* Return status */
110
111   for (i = PREV_INDEX(cur_request_index); i != cur_request_index;
112        i = PREV_INDEX(i))
113     {
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 */
118         {
119           status = TRUE;
120           sendto(s, requests[i].out_pkt, requests[i].out_pktlen,
121                  0, (struct sockaddr *)&sin, addrlen);
122           break;
123         }
124     }
125
126   return status;
127 }
128
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. */
133 void respond(int status, char *text)
134 {
135   CUR_REQ.out_pktlen = sizeof(CUR_REQ.out_pkt);
136
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);
142
143   cur_request_index = NEXT_INDEX(cur_request_index);
144 }
145
146 void get_request(struct msg *message)
147 {
148   static char packet[BUFSIZ];   /* Buffer for incoming packet */
149   int pktlen;                   /* Length of incoming packet */
150   int status = FAILURE;         /* Error status */
151
152   /* Sit around waiting for requests from the client. */
153   for (;;)
154     {
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)
160         {
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);
166         }
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)
175         {
176           /* If error, format packet to send back to the client */
177           respond(status, NULL);
178         }
179       else
180         {
181           /* Check for retransmitted packet.  handle_retransmitted()
182              returns true if it handled a retransmitted packet. */
183           if (!handle_retransmitted())
184             break;
185         }
186     }
187 }
188
189 void report(int status, char *message)
190 {
191   respond(status, message);
192 }
193
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. */
197 int format_pkt(char *packet, int *pktlenp, U_32BIT seqno,
198                int cl_status, char *message)
199 {
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 */
219     {
220       status = FAILURE; /* Message was truncated */
221       /* Truncate the message */
222       message[len - 1] = '\0';
223     }
224
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;
230 }
231
232 /* The ureg_validate_char variable and routine were taken verbatim
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
238  * the string.  Legal characters are printing chars other than
239  * ", *, ?, \, [ and ].
240  */
241 static 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
260 int ureg_validate_char(register char *s)
261 {
262   while (*s)
263     {
264       if (illegalchars[*s++])
265         return FAILURE;
266     }
267   return SUCCESS;
268 }
269
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. */
273 int parse_pkt(char *packet, int pktlen, struct msg *message)
274 {
275   int status = SUCCESS; /* Error status */
276
277   com_err(whoami, 0, "Packet received");
278
279   if (pktlen < sizeof(U_32BIT))
280     status = UREG_BROKEN_PACKET;
281   if (status == SUCCESS)
282     {
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;
290     }
291
292   if (status == SUCCESS)
293     {
294       packet += sizeof(U_32BIT);
295       pktlen -= sizeof(U_32BIT);
296
297       if (pktlen < sizeof(U_32BIT))
298         status = UREG_BROKEN_PACKET;
299     }
300
301   if (status == SUCCESS)
302     {
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;
311     }
312
313   if (status == SUCCESS)
314     {
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)
324         {
325           com_err(whoami, 0, "Packet contains invalid characters.");
326           status = UREG_USER_NOT_FOUND;
327         }
328       else
329         {
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;
339         }
340     }
341
342   if (status == SUCCESS)
343     {
344       /* Skip over the null */
345       packet++, pktlen--;
346
347       if (ureg_validate_char(packet) != SUCCESS)
348         {
349           com_err(whoami, 0, "Packet contains invalid characters.");
350           status = UREG_USER_NOT_FOUND;
351         }
352       else
353         {
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;
361         }
362     }
363
364   if (status == SUCCESS)
365     {
366       packet++, pktlen--;
367
368       if (pktlen <= 0)
369         status = UREG_BROKEN_PACKET;
370     }
371
372   /* Extract encrypted information from packet */
373   message->encrypted = packet;
374   message->encrypted_len = pktlen;
375
376   if (status == SUCCESS)
377     {
378       com_err(whoami, status, "Request %d for %s %s", message->request,
379               message->first, message->last);
380     }
381   else
382     com_err(whoami, status, " - parse packet failed.");
383
384   return status;
385 }
386
387
388 u_long cur_req_sender(void)
389 {
390   return CUR_REQ.ip_address;
391 }
This page took 0.07199 seconds and 5 git commands to generate.