]> git.saurik.com Git - apple/network_cmds.git/blame - identd.tproj/parse.c
network_cmds-77.tar.gz
[apple/network_cmds.git] / identd.tproj / parse.c
CommitLineData
b7080c8e
A
1/*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24/*
25** $Id: parse.c,v 1.2 2000/10/03 02:38:32 lindak Exp $
26**
27** parse.c This file contains the protocol parser
28**
29** This program is in the public domain and may be used freely by anyone
30** who wants to.
31**
32** Last update: 6 Dec 1992
33**
34** Please send bug fixes/bug reports to: Peter Eriksson <pen@lysator.liu.se>
35*/
36
37#include <stdio.h>
38#include <errno.h>
39#include <ctype.h>
40#include <pwd.h>
41
42#include <sys/types.h>
43#include <netinet/in.h>
44
45#ifndef HPUX7
46# include <arpa/inet.h>
47#endif
48
49#include <nlist.h>
50#include <kvm.h>
51
52#include <sys/types.h>
53#include <sys/stat.h>
54
55#if defined(MIPS) || defined(BSD43)
56extern int errno;
57#endif
58
59#include "identd.h"
60#include "error.h"
61
62extern void *malloc();
63
64/*
65** This function will eat whitespace characters until
66** either a non-whitespace character is read, or EOF
67** occurs. This function is only used if the "-m" option
68** is enabled.
69*/
70static int eat_whitespace()
71{
72 int c;
73
74
75 while ((c = getchar()) != EOF &&
76 !(c == '\r' || c == '\n'))
77 ;
78
79 if (c != EOF)
80 while ((c = getchar()) != EOF &&
81 (c == ' ' || c == '\t' || c == '\n' || c == '\r'))
82 ;
83
84 if (c != EOF)
85 ungetc(c, stdin);
86
87 return (c != EOF);
88}
89
90
91#ifdef INCLUDE_EXTENSIONS
92/*
93** Validate an indirect request
94*/
95static int valid_fhost(faddr, password)
96 struct in_addr *faddr;
97 char *password;
98{
99 if (indirect_host == NULL)
100 return 0;
101
102 if (strcmp(indirect_host, "*") != 0)
103 {
104 if (isdigit(indirect_host[0]))
105 {
106 if (strcmp(inet_ntoa(*faddr), indirect_host))
107 {
108 syslog(LOG_NOTICE, "valid_fhost: access denied for: %s",
109 gethost(faddr));
110 return 0;
111 }
112 }
113 else
114 {
115 if (strcmp(gethost(faddr), indirect_host))
116 {
117 syslog(LOG_NOTICE, "valid_fhost: access denied for: %s",
118 gethost(faddr));
119 return 0;
120 }
121 }
122 }
123
124 if (indirect_password == NULL)
125 return 1;
126
127 if (strcmp(password, indirect_password))
128 {
129 syslog(LOG_NOTICE, "valid_fhost: invalid password from: %s",
130 gethost(faddr));
131 return 0;
132 }
133
134 return 1;
135}
136#endif
137
138/*
139** A small routine to check for the existance of the ".noident"
140** file in a users home directory.
141*/
142static int check_noident(homedir)
143 char *homedir;
144{
145 char *tmp_path;
146 struct stat sbuf;
147 int rcode;
148
149
150 if (!homedir)
151 return 0;
152
153 tmp_path = (char *) malloc(strlen(homedir) + sizeof("/.noident") + 1);
154 if (!tmp_path)
155 return 0;
156
157 strcpy(tmp_path, homedir);
158 strcat(tmp_path, "/.noident");
159
160 rcode = stat(tmp_path, &sbuf);
161 free(tmp_path);
162
163 return (rcode == 0);
164}
165
166
167int parse(fp, laddr, faddr)
168 FILE *fp;
169 struct in_addr *laddr, *faddr;
170{
171 int uid, try, rcode;
172 struct passwd *pwp;
173 char lhostaddr[16];
174 char fhostaddr[16];
175 char password[33];
176#ifdef INCLUDE_EXTENSIONS
177 char arg[33];
178 int c;
179#endif
180 struct in_addr laddr2;
181 struct in_addr faddr2;
182
183
184 if (debug_flag && syslog_flag)
185 syslog(LOG_DEBUG, "In function parse()");
186
187 /*
188 ** Get the local/foreign port pair from the luser
189 */
190 do
191 {
192 if (debug_flag && syslog_flag)
193 syslog(LOG_DEBUG, " Before fscanf()");
194
195 faddr2 = *faddr;
196 laddr2 = *laddr;
197 lport = fport = 0;
198 lhostaddr[0] = fhostaddr[0] = password[0] = '\0';
199
200 /* Read query from client */
201 rcode = fscanf(fp, " %d , %d", &lport, &fport);
202
203#ifdef INCLUDE_EXTENSIONS
204 /*
205 ** Do additional parsing in case of extended request
206 */
207 if (rcode == 0)
208 {
209 rcode = fscanf(fp, "%32[^ \t\n\r:]", arg);
210
211 /* Skip leading space up to EOF, EOL or non-space char */
212 while ((c = getc(fp)) == ' ' || c == '\t')
213 ;
214
215 if (rcode <= 0)
216 {
217 printf("%d , %d : ERROR : %s\r\n",
218 lport, fport,
219 unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
220 continue;
221 }
222
223 /*
224 ** Non-standard extended request, returns with Pidentd
225 ** version information
226 */
227 if (strcmp(arg, "VERSION") == 0)
228 {
229 printf("%d , %d : ERROR : X-VERSION : %s\r\n", lport, fport,
230 version);
231 continue;
232 }
233
234 /*
235 ** Non-standard extended proxy request
236 */
237 else if (strcmp(arg, "PROXY") == 0 && c == ':')
238 {
239 /* We have a colon char, check for port numbers */
240 rcode = fscanf(fp, " %d , %d : %15[0-9.] , %15[0-9.]",
241 &lport, &fport, fhostaddr, lhostaddr);
242
243 if (!(rcode == 3 || rcode == 4))
244 {
245 printf("%d , %d : ERROR : %s\r\n",
246 lport, fport,
247 unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
248 continue;
249 }
250
251 if (rcode == 4)
252 laddr2.s_addr = inet_addr(lhostaddr);
253
254 faddr2.s_addr = inet_addr(fhostaddr);
255
256 proxy(&laddr2, &faddr2, lport, fport, NULL);
257 continue;
258 }
259
260 /*
261 ** Non-standard extended remote indirect request
262 */
263 else if (strcmp(arg, "REMOTE") == 0 && c == ':')
264 {
265 /* We have a colon char, check for port numbers */
266 rcode = fscanf(fp, " %d , %d", &lport, &fport);
267
268 /* Skip leading space up to EOF, EOL or non-space char */
269 while ((c = getc(fp)) == ' ' || c == '\t')
270 ;
271
272 if (rcode != 2 || c != ':')
273 {
274 printf("%d , %d : ERROR : %s\r\n",
275 lport, fport,
276 unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
277 continue;
278 }
279
280 /* We have a colon char, check for addr and password */
281 rcode = fscanf(fp, " %15[0-9.] , %32[^ \t\r\n]",
282 fhostaddr, password);
283 if (rcode > 0)
284 rcode += 2;
285 else
286 {
287 printf("%d , %d : ERROR : %s\r\n",
288 lport, fport,
289 unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
290 continue;
291 }
292
293 /*
294 ** Verify that the host originating the indirect request
295 ** is allowed to do that
296 */
297 if (!valid_fhost(faddr, password))
298 {
299 printf("%d , %d : ERROR : %s\r\n",
300 lport, fport,
301 unknown_flag ? "UNKNOWN-ERROR" : "X-ACCESS-DENIED");
302 continue;
303 }
304
305 faddr2.s_addr = inet_addr(fhostaddr);
306 }
307
308 else
309 {
310 printf("%d , %d : ERROR : %s\r\n",
311 lport, fport,
312 unknown_flag ? "UNKNOWN-ERROR" : "X-INVALID-REQUEST");
313 continue;
314 }
315 }
316#endif /* EXTENSIONS */
317
318 if (rcode < 2 || lport < 1 || lport > 65535 || fport < 1 || fport > 65535)
319 {
320 if (syslog_flag && rcode > 0)
321 syslog(LOG_NOTICE, "scanf: invalid-port(s): %d , %d from %s",
322 lport, fport, gethost(faddr));
323
324 printf("%d , %d : ERROR : %s\r\n",
325 lport, fport,
326 unknown_flag ? "UNKNOWN-ERROR" : "INVALID-PORT");
327 continue;
328 }
329
330 if (syslog_flag && verbose_flag)
331 syslog(LOG_NOTICE, "request for (%d,%d) from %s",
332 lport, fport, gethost(faddr));
333
334 if (debug_flag && syslog_flag)
335 syslog(LOG_DEBUG, " After fscanf(), before k_getuid()");
336
337 /*
338 ** Next - get the specific TCP connection and return the
339 ** uid - user number.
340 **
341 ** Try to fetch the information 5 times incase the
342 ** kernel changed beneath us and we missed or took
343 ** a fault.
344 */
345 for (try = 0;
346 (try < 5 &&
347 k_getuid(&faddr2, htons(fport), laddr, htons(lport), &uid) == -1);
348 try++)
349 ;
350
351 if (try >= 5)
352 {
353 if (syslog_flag)
354 syslog(LOG_DEBUG, "Returned: %d , %d : NO-USER", lport, fport);
355
356 printf("%d , %d : ERROR : %s\r\n",
357 lport, fport,
358 unknown_flag ? "UNKNOWN-ERROR" : "NO-USER");
359 continue;
360 }
361
362 if (try > 0 && syslog_flag)
363 syslog(LOG_NOTICE, "k_getuid retries: %d", try);
364
365 if (debug_flag && syslog_flag)
366 syslog(LOG_DEBUG, " After k_getuid(), before getpwuid()");
367
368 /*
369 ** Then we should try to get the username. If that fails we
370 ** return it as an OTHER identifier
371 */
372 pwp = getpwuid(uid);
373
374 if (!pwp)
375 {
376 if (syslog_flag)
377 syslog(LOG_WARNING, "getpwuid() could not map uid (%d) to name",
378 uid);
379
380 printf("%d , %d : USERID : OTHER%s%s : %d\r\n",
381 lport, fport,
382 charset_name ? " , " : "",
383 charset_name ? charset_name : "",
384 uid);
385 continue;
386 }
387
388 /*
389 ** Hey! We finally made it!!!
390 */
391 if (syslog_flag)
392 syslog(LOG_DEBUG, "Successful lookup: %d , %d : %s",
393 lport, fport, pwp->pw_name);
394
395 if (noident_flag && check_noident(pwp->pw_dir))
396 {
397 if (syslog_flag && verbose_flag)
398 syslog(LOG_NOTICE, "user %s requested HIDDEN-USER for host %s: %d, %d",
399 pwp->pw_name,
400 gethost(faddr),
401 lport, fport);
402
403 printf("%d , %d : ERROR : HIDDEN-USER\r\n",
404 lport, fport);
405 continue;
406 }
407
408 if (number_flag)
409 printf("%d , %d : USERID : OTHER%s%s : %d\r\n",
410 lport, fport,
411 charset_name ? " , " : "",
412 charset_name ? charset_name : "",
413 uid);
414 else
415 printf("%d , %d : USERID : %s%s%s : %s\r\n",
416 lport, fport,
417 other_flag ? "OTHER" : "UNIX",
418 charset_name ? " , " : "",
419 charset_name ? charset_name : "",
420 pwp->pw_name);
421
422 } while(fflush(stdout), fflush(stderr), multi_flag && eat_whitespace());
423
424 return 0;
425}