3 * $Id: check.c,v 1.1 1997/07/21 13:47:53 mdw Exp $
5 * Check validity of requests
10 /*----- Licencing notice --------------------------------------------------*
12 * This file is part of `become'
14 * `Become' is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * `Become' is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with `become'; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 /*----- Revision history --------------------------------------------------*
32 * Revision 1.1 1997/07/21 13:47:53 mdw
37 /*----- Header files ------------------------------------------------------*/
39 /* --- ANSI headers --- */
48 /* --- Unix headers --- */
51 #include <sys/types.h>
52 #include <sys/socket.h>
54 #include <netinet/in.h>
56 #include <arpa/inet.h>
61 /* --- Local headers --- */
74 /*----- Main code ---------------------------------------------------------*/
76 /* --- @check__client@ --- *
78 * Arguments: @request *rq@ = pointer to request buffer
79 * @const char *serv@ = pointer to the server
80 * @int port@ = port number to use
82 * Returns: Nonzero if OK, zero if forbidden
84 * Use: Contacts a server to decide whether the request is OK.
87 static int check__client(request
*rq
, const char *serv
, int port
)
90 struct sockaddr_in ssin
;
91 unsigned char crq
[crq_size
];
92 unsigned char k
[IDEA_KEYSIZE
];
93 unsigned char sk
[IDEA_KEYSIZE
];
97 /* --- Create my socket --- */
99 if ((fd
= socket(PF_INET
, SOCK_DGRAM
, 0)) < 0)
100 die("couldn't create socket: %s", strerror(errno
));
102 /* --- Bind myself to some address --- */
105 struct sockaddr_in sin
;
107 sin
.sin_family
= AF_INET
;
109 sin
.sin_addr
.s_addr
= htonl(INADDR_ANY
);
111 if (bind(fd
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0)
112 die("couldn't bind socket to address: %s", strerror(errno
));
115 /* --- Find the server's address --- */
120 /* --- Resolve the server's name --- */
122 if ((he
= gethostbyname(serv
)) == 0)
123 die("couldn't find server host `%s'", serv
);
125 /* --- Build the address block --- */
127 ssin
.sin_family
= AF_INET
;
128 ssin
.sin_port
= htons(port
);
129 memcpy(&ssin
.sin_addr
, he
->h_addr
, sizeof(struct in_addr
));
132 /* --- Read in the encryption key --- */
137 if ((fp
= fopen(file_KEY
, "r")) == 0) {
138 die("couldn't open key file `%s': %s", file_KEY
,
141 tx_getBits(k
, 128, fp
);
144 /* --- Now build a request packet --- */
148 crypt_packRequest(rq
, crq
, t
, pid
, k
, sk
);
150 /* --- Send the packet to the server --- */
152 if (sendto(fd
, (char *)crq
, sizeof(crq
), 0,
153 (struct sockaddr
*)&ssin
, sizeof(ssin
)) < 0) {
155 die("couldn't send request to server: %s", strerror(errno
));
159 /* --- Now wait for a reply --- */
163 struct timeval when
, now
, tv
;
165 gettimeofday(&when
, 0);
171 /* --- Sort out when to return --- */
173 gettimeofday(&now
, 0);
174 if (now
.tv_usec
> when
.tv_usec
) {
175 now
.tv_usec
-= 1000000;
178 tv
.tv_sec
= when
.tv_sec
- now
.tv_sec
;
179 tv
.tv_usec
= when
.tv_usec
- now
.tv_usec
;
181 /* --- Sort out file descriptors to watch --- */
186 /* --- Wait for them --- */
188 i
= select(FD_SETSIZE
, &fds
, 0, 0, &tv
);
190 die("no answer from server");
192 die("error waiting for reply: %s", strerror(errno
));
194 /* --- A reply should be waiting now --- */
197 struct sockaddr_in sin
;
198 int slen
= sizeof(sin
);
199 unsigned char buff
[256];
202 /* --- Read the reply data --- */
204 if (recvfrom(fd
, (char *)buff
, sizeof(buff
), 0,
205 (struct sockaddr
*)&sin
, &slen
) < 0)
206 die("error reading server's reply: %s", strerror(errno
));
208 /* --- Verify the sender --- */
210 if (sin
.sin_addr
.s_addr
!= ssin
.sin_addr
.s_addr
||
211 sin
.sin_port
!= ssin
.sin_port
)
214 /* --- Unpack and verify the response --- */
216 answer
= crypt_unpackReply(buff
, sk
, t
, pid
);
224 die("internal error: can't get here in check_client");
230 * Arguments: @request *rq@ = pointer to request buffer
232 * Returns: Nonzero if OK, zero if forbidden
234 * Use: Checks to see if the request is acceptable.
237 int check(request
*rq
)
241 /* --- Check if we need to talk to a server --- */
243 if ((fp
= fopen(file_SERVER
, "r")) != 0) {
248 if (fscanf(fp
, " %63[^: \t] ", buff
) < 1)
249 die("error in `%s'", file_SERVER
);
256 if ((se
= getservbyname(b
, 0)) != 0)
257 port
= ntohs(se
->s_port
);
258 else if ((port
= atoi(b
)) == 0)
259 die("error in `%s'", file_SERVER
);
263 if ((se
= getservbyname(quis(), "udp")) == 0)
264 die("no idea which port to use");
265 port
= ntohs(se
->s_port
);
268 return (check__client(rq
, buff
, port
));
271 /* --- Read the configuration in and go --- */
273 if ((fp
= fopen(file_RULES
, "r")) == 0) {
274 die("couldn't read configuration file `%s': %s",
275 file_RULES
, strerror(errno
));
283 return (rule_check(rq
));
286 /*----- That's all, folks -------------------------------------------------*/