ReactOS 0.4.16-dev-819-g75c0dc0
auth.c
Go to the documentation of this file.
1/*
2 * auth.c - PPP authentication and phase control.
3 *
4 * Copyright (c) 1993-2002 Paul Mackerras. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * 2. The name(s) of the authors of this software must not be used to
14 * endorse or promote products derived from this software without
15 * prior written permission.
16 *
17 * 3. Redistributions of any form whatsoever must retain the following
18 * acknowledgment:
19 * "This product includes software developed by Paul Mackerras
20 * <paulus@samba.org>".
21 *
22 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 *
30 * Derived from main.c, which is:
31 *
32 * Copyright (c) 1984-2000 Carnegie Mellon University. All rights reserved.
33 *
34 * Redistribution and use in source and binary forms, with or without
35 * modification, are permitted provided that the following conditions
36 * are met:
37 *
38 * 1. Redistributions of source code must retain the above copyright
39 * notice, this list of conditions and the following disclaimer.
40 *
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in
43 * the documentation and/or other materials provided with the
44 * distribution.
45 *
46 * 3. The name "Carnegie Mellon University" must not be used to
47 * endorse or promote products derived from this software without
48 * prior written permission. For permission or any legal
49 * details, please contact
50 * Office of Technology Transfer
51 * Carnegie Mellon University
52 * 5000 Forbes Avenue
53 * Pittsburgh, PA 15213-3890
54 * (412) 268-4387, fax: (412) 268-7395
55 * tech-transfer@andrew.cmu.edu
56 *
57 * 4. Redistributions of any form whatsoever must retain the following
58 * acknowledgment:
59 * "This product includes software developed by Computing Services
60 * at Carnegie Mellon University (http://www.cmu.edu/computing/)."
61 *
62 * CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
63 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
64 * AND FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE
65 * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
66 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
67 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
68 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
69 */
70
71#include "netif/ppp/ppp_opts.h"
72#if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
73
74#if 0 /* UNUSED */
75#include <stdio.h>
76#include <stddef.h>
77#include <stdlib.h>
78#include <unistd.h>
79#include <errno.h>
80#include <pwd.h>
81#include <grp.h>
82#include <string.h>
83#include <sys/types.h>
84#include <sys/stat.h>
85#include <sys/socket.h>
86#include <utmp.h>
87#include <fcntl.h>
88#if defined(_PATH_LASTLOG) && defined(__linux__)
89#include <lastlog.h>
90#endif
91
92#include <netdb.h>
93#include <netinet/in.h>
94#include <arpa/inet.h>
95
96#ifdef HAS_SHADOW
97#include <shadow.h>
98#ifndef PW_PPP
99#define PW_PPP PW_LOGIN
100#endif
101#endif
102
103#include <time.h>
104#endif /* UNUSED */
105
106#include "netif/ppp/ppp_impl.h"
107
108#include "netif/ppp/fsm.h"
109#include "netif/ppp/lcp.h"
110#if CCP_SUPPORT
111#include "netif/ppp/ccp.h"
112#endif /* CCP_SUPPORT */
113#if ECP_SUPPORT
114#include "netif/ppp/ecp.h"
115#endif /* ECP_SUPPORT */
116#include "netif/ppp/ipcp.h"
117#if PAP_SUPPORT
118#include "netif/ppp/upap.h"
119#endif /* PAP_SUPPORT */
120#if CHAP_SUPPORT
121#include "netif/ppp/chap-new.h"
122#endif /* CHAP_SUPPORT */
123#if EAP_SUPPORT
124#include "netif/ppp/eap.h"
125#endif /* EAP_SUPPORT */
126#if CBCP_SUPPORT
127#include "netif/ppp/cbcp.h"
128#endif
129
130#if 0 /* UNUSED */
131#include "session.h"
132#endif /* UNUSED */
133
134#if 0 /* UNUSED */
135/* Bits in scan_authfile return value */
136#define NONWILD_SERVER 1
137#define NONWILD_CLIENT 2
138
139#define ISWILD(word) (word[0] == '*' && word[1] == 0)
140#endif /* UNUSED */
141
142#if 0 /* UNUSED */
143/* List of addresses which the peer may use. */
144static struct permitted_ip *addresses[NUM_PPP];
145
146/* Wordlist giving addresses which the peer may use
147 without authenticating itself. */
148static struct wordlist *noauth_addrs;
149
150/* Remote telephone number, if available */
151char remote_number[MAXNAMELEN];
152
153/* Wordlist giving remote telephone numbers which may connect. */
154static struct wordlist *permitted_numbers;
155
156/* Extra options to apply, from the secrets file entry for the peer. */
157static struct wordlist *extra_options;
158#endif /* UNUSED */
159
160#if 0 /* UNUSED */
161/* Set if we require authentication only because we have a default route. */
162static bool default_auth;
163
164/* Hook to enable a plugin to control the idle time limit */
165int (*idle_time_hook) (struct ppp_idle *) = NULL;
166
167/* Hook for a plugin to say whether we can possibly authenticate any peer */
168int (*pap_check_hook) (void) = NULL;
169
170/* Hook for a plugin to check the PAP user and password */
171int (*pap_auth_hook) (char *user, char *passwd, char **msgp,
172 struct wordlist **paddrs,
173 struct wordlist **popts) = NULL;
174
175/* Hook for a plugin to know about the PAP user logout */
176void (*pap_logout_hook) (void) = NULL;
177
178/* Hook for a plugin to get the PAP password for authenticating us */
179int (*pap_passwd_hook) (char *user, char *passwd) = NULL;
180
181/* Hook for a plugin to say if we can possibly authenticate a peer using CHAP */
182int (*chap_check_hook) (void) = NULL;
183
184/* Hook for a plugin to get the CHAP password for authenticating us */
185int (*chap_passwd_hook) (char *user, char *passwd) = NULL;
186
187/* Hook for a plugin to say whether it is OK if the peer
188 refuses to authenticate. */
189int (*null_auth_hook) (struct wordlist **paddrs,
190 struct wordlist **popts) = NULL;
191
192int (*allowed_address_hook) (u32_t addr) = NULL;
193#endif /* UNUSED */
194
195#ifdef HAVE_MULTILINK
196/* Hook for plugin to hear when an interface joins a multilink bundle */
197void (*multilink_join_hook) (void) = NULL;
198#endif
199
200#if PPP_NOTIFY
201/* A notifier for when the peer has authenticated itself,
202 and we are proceeding to the network phase. */
203struct notifier *auth_up_notifier = NULL;
204
205/* A notifier for when the link goes down. */
206struct notifier *link_down_notifier = NULL;
207#endif /* PPP_NOTIFY */
208
209/*
210 * Option variables.
211 */
212#if 0 /* MOVED TO ppp_settings */
213bool uselogin = 0; /* Use /etc/passwd for checking PAP */
214bool session_mgmt = 0; /* Do session management (login records) */
215bool cryptpap = 0; /* Passwords in pap-secrets are encrypted */
216bool refuse_pap = 0; /* Don't wanna auth. ourselves with PAP */
217bool refuse_chap = 0; /* Don't wanna auth. ourselves with CHAP */
218bool refuse_eap = 0; /* Don't wanna auth. ourselves with EAP */
219#if MSCHAP_SUPPORT
220bool refuse_mschap = 0; /* Don't wanna auth. ourselves with MS-CHAP */
221bool refuse_mschap_v2 = 0; /* Don't wanna auth. ourselves with MS-CHAPv2 */
222#else /* MSCHAP_SUPPORT */
223bool refuse_mschap = 1; /* Don't wanna auth. ourselves with MS-CHAP */
224bool refuse_mschap_v2 = 1; /* Don't wanna auth. ourselves with MS-CHAPv2 */
225#endif /* MSCHAP_SUPPORT */
226bool usehostname = 0; /* Use hostname for our_name */
227bool auth_required = 0; /* Always require authentication from peer */
228bool allow_any_ip = 0; /* Allow peer to use any IP address */
229bool explicit_remote = 0; /* User specified explicit remote name */
230bool explicit_user = 0; /* Set if "user" option supplied */
231bool explicit_passwd = 0; /* Set if "password" option supplied */
232char remote_name[MAXNAMELEN]; /* Peer's name for authentication */
233static char *uafname; /* name of most recent +ua file */
234
235extern char *crypt (const char *, const char *);
236#endif /* UNUSED */
237/* Prototypes for procedures local to this file. */
238
239static void network_phase(ppp_pcb *pcb);
240#if PPP_IDLETIMELIMIT
241static void check_idle(void *arg);
242#endif /* PPP_IDLETIMELIMIT */
243#if PPP_MAXCONNECT
244static void connect_time_expired(void *arg);
245#endif /* PPP_MAXCONNECT */
246#if 0 /* UNUSED */
247static int null_login (int);
248/* static int get_pap_passwd (char *); */
249static int have_pap_secret (int *);
250static int have_chap_secret (char *, char *, int, int *);
251static int have_srp_secret (char *client, char *server, int need_ip,
252 int *lacks_ipp);
253static int ip_addr_check (u32_t, struct permitted_ip *);
254static int scan_authfile (FILE *, char *, char *, char *,
255 struct wordlist **, struct wordlist **,
256 char *, int);
257static void free_wordlist (struct wordlist *);
258static void set_allowed_addrs (int, struct wordlist *, struct wordlist *);
259static int some_ip_ok (struct wordlist *);
260static int setupapfile (char **);
261static int privgroup (char **);
262static int set_noauth_addr (char **);
263static int set_permitted_number (char **);
264static void check_access (FILE *, char *);
265static int wordlist_count (struct wordlist *);
266#endif /* UNUSED */
267
268#ifdef MAXOCTETS
269static void check_maxoctets (void *);
270#endif
271
272#if PPP_OPTIONS
273/*
274 * Authentication-related options.
275 */
276option_t auth_options[] = {
277 { "auth", o_bool, &auth_required,
278 "Require authentication from peer", OPT_PRIO | 1 },
279 { "noauth", o_bool, &auth_required,
280 "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV,
281 &allow_any_ip },
282 { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap,
283 "Require PAP authentication from peer",
284 OPT_PRIOSUB | 1, &auth_required },
285 { "+pap", o_bool, &lcp_wantoptions[0].neg_upap,
286 "Require PAP authentication from peer",
287 OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required },
288 { "require-chap", o_bool, &auth_required,
289 "Require CHAP authentication from peer",
290 OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5,
291 &lcp_wantoptions[0].chap_mdtype },
292 { "+chap", o_bool, &auth_required,
293 "Require CHAP authentication from peer",
294 OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MD5,
295 &lcp_wantoptions[0].chap_mdtype },
296#if MSCHAP_SUPPORT
297 { "require-mschap", o_bool, &auth_required,
298 "Require MS-CHAP authentication from peer",
299 OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT,
300 &lcp_wantoptions[0].chap_mdtype },
301 { "+mschap", o_bool, &auth_required,
302 "Require MS-CHAP authentication from peer",
303 OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT,
304 &lcp_wantoptions[0].chap_mdtype },
305 { "require-mschap-v2", o_bool, &auth_required,
306 "Require MS-CHAPv2 authentication from peer",
307 OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2,
308 &lcp_wantoptions[0].chap_mdtype },
309 { "+mschap-v2", o_bool, &auth_required,
310 "Require MS-CHAPv2 authentication from peer",
311 OPT_ALIAS | OPT_PRIOSUB | OPT_A2OR | MDTYPE_MICROSOFT_V2,
312 &lcp_wantoptions[0].chap_mdtype },
313#endif /* MSCHAP_SUPPORT */
314#if 0
315 { "refuse-pap", o_bool, &refuse_pap,
316 "Don't agree to auth to peer with PAP", 1 },
317 { "-pap", o_bool, &refuse_pap,
318 "Don't allow PAP authentication with peer", OPT_ALIAS | 1 },
319 { "refuse-chap", o_bool, &refuse_chap,
320 "Don't agree to auth to peer with CHAP",
321 OPT_A2CLRB | MDTYPE_MD5,
322 &lcp_allowoptions[0].chap_mdtype },
323 { "-chap", o_bool, &refuse_chap,
324 "Don't allow CHAP authentication with peer",
325 OPT_ALIAS | OPT_A2CLRB | MDTYPE_MD5,
326 &lcp_allowoptions[0].chap_mdtype },
327#endif
328#if MSCHAP_SUPPORT
329#if 0
330 { "refuse-mschap", o_bool, &refuse_mschap,
331 "Don't agree to auth to peer with MS-CHAP",
332 OPT_A2CLRB | MDTYPE_MICROSOFT,
333 &lcp_allowoptions[0].chap_mdtype },
334 { "-mschap", o_bool, &refuse_mschap,
335 "Don't allow MS-CHAP authentication with peer",
336 OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT,
337 &lcp_allowoptions[0].chap_mdtype },
338 { "refuse-mschap-v2", o_bool, &refuse_mschap_v2,
339 "Don't agree to auth to peer with MS-CHAPv2",
340 OPT_A2CLRB | MDTYPE_MICROSOFT_V2,
341 &lcp_allowoptions[0].chap_mdtype },
342 { "-mschap-v2", o_bool, &refuse_mschap_v2,
343 "Don't allow MS-CHAPv2 authentication with peer",
344 OPT_ALIAS | OPT_A2CLRB | MDTYPE_MICROSOFT_V2,
345 &lcp_allowoptions[0].chap_mdtype },
346#endif
347#endif /* MSCHAP_SUPPORT*/
348#if EAP_SUPPORT
349 { "require-eap", o_bool, &lcp_wantoptions[0].neg_eap,
350 "Require EAP authentication from peer", OPT_PRIOSUB | 1,
351 &auth_required },
352#if 0
353 { "refuse-eap", o_bool, &refuse_eap,
354 "Don't agree to authenticate to peer with EAP", 1 },
355#endif
356#endif /* EAP_SUPPORT */
357 { "name", o_string, our_name,
358 "Set local name for authentication",
359 OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN },
360
361 { "+ua", o_special, (void *)setupapfile,
362 "Get PAP user and password from file",
363 OPT_PRIO | OPT_A2STRVAL, &uafname },
364
365#if 0
366 { "user", o_string, user,
367 "Set name for auth with peer", OPT_PRIO | OPT_STATIC,
368 &explicit_user, MAXNAMELEN },
369
370 { "password", o_string, passwd,
371 "Password for authenticating us to the peer",
372 OPT_PRIO | OPT_STATIC | OPT_HIDE,
373 &explicit_passwd, MAXSECRETLEN },
374#endif
375
376 { "usehostname", o_bool, &usehostname,
377 "Must use hostname for authentication", 1 },
378
379 { "remotename", o_string, remote_name,
380 "Set remote name for authentication", OPT_PRIO | OPT_STATIC,
381 &explicit_remote, MAXNAMELEN },
382
383 { "login", o_bool, &uselogin,
384 "Use system password database for PAP", OPT_A2COPY | 1 ,
385 &session_mgmt },
386 { "enable-session", o_bool, &session_mgmt,
387 "Enable session accounting for remote peers", OPT_PRIV | 1 },
388
389 { "papcrypt", o_bool, &cryptpap,
390 "PAP passwords are encrypted", 1 },
391
392 { "privgroup", o_special, (void *)privgroup,
393 "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST },
394
395 { "allow-ip", o_special, (void *)set_noauth_addr,
396 "Set IP address(es) which can be used without authentication",
397 OPT_PRIV | OPT_A2LIST },
398
399 { "remotenumber", o_string, remote_number,
400 "Set remote telephone number for authentication", OPT_PRIO | OPT_STATIC,
401 NULL, MAXNAMELEN },
402
403 { "allow-number", o_special, (void *)set_permitted_number,
404 "Set telephone number(s) which are allowed to connect",
405 OPT_PRIV | OPT_A2LIST },
406
407 { NULL }
408};
409#endif /* PPP_OPTIONS */
410
411#if 0 /* UNUSED */
412/*
413 * setupapfile - specifies UPAP info for authenticating with peer.
414 */
415static int
416setupapfile(argv)
417 char **argv;
418{
419 FILE *ufile;
420 int l;
421 uid_t euid;
422 char u[MAXNAMELEN], p[MAXSECRETLEN];
423 char *fname;
424
425 lcp_allowoptions[0].neg_upap = 1;
426
427 /* open user info file */
428 fname = strdup(*argv);
429 if (fname == NULL)
430 novm("+ua file name");
431 euid = geteuid();
432 if (seteuid(getuid()) == -1) {
433 option_error("unable to reset uid before opening %s: %m", fname);
434 return 0;
435 }
436 ufile = fopen(fname, "r");
437 if (seteuid(euid) == -1)
438 fatal("unable to regain privileges: %m");
439 if (ufile == NULL) {
440 option_error("unable to open user login data file %s", fname);
441 return 0;
442 }
443 check_access(ufile, fname);
444 uafname = fname;
445
446 /* get username */
447 if (fgets(u, MAXNAMELEN - 1, ufile) == NULL
448 || fgets(p, MAXSECRETLEN - 1, ufile) == NULL) {
449 fclose(ufile);
450 option_error("unable to read user login data file %s", fname);
451 return 0;
452 }
453 fclose(ufile);
454
455 /* get rid of newlines */
456 l = strlen(u);
457 if (l > 0 && u[l-1] == '\n')
458 u[l-1] = 0;
459 l = strlen(p);
460 if (l > 0 && p[l-1] == '\n')
461 p[l-1] = 0;
462
463 if (override_value("user", option_priority, fname)) {
464 strlcpy(ppp_settings.user, u, sizeof(ppp_settings.user));
465 explicit_user = 1;
466 }
467 if (override_value("passwd", option_priority, fname)) {
468 strlcpy(ppp_settings.passwd, p, sizeof(ppp_settings.passwd));
469 explicit_passwd = 1;
470 }
471
472 return (1);
473}
474
475/*
476 * privgroup - allow members of the group to have privileged access.
477 */
478static int
479privgroup(argv)
480 char **argv;
481{
482 struct group *g;
483 int i;
484
485 g = getgrnam(*argv);
486 if (g == 0) {
487 option_error("group %s is unknown", *argv);
488 return 0;
489 }
490 for (i = 0; i < ngroups; ++i) {
491 if (groups[i] == g->gr_gid) {
492 privileged = 1;
493 break;
494 }
495 }
496 return 1;
497}
498
499
500/*
501 * set_noauth_addr - set address(es) that can be used without authentication.
502 * Equivalent to specifying an entry like `"" * "" addr' in pap-secrets.
503 */
504static int
505set_noauth_addr(argv)
506 char **argv;
507{
508 char *addr = *argv;
509 int l = strlen(addr) + 1;
510 struct wordlist *wp;
511
512 wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l);
513 if (wp == NULL)
514 novm("allow-ip argument");
515 wp->word = (char *) (wp + 1);
516 wp->next = noauth_addrs;
517 MEMCPY(wp->word, addr, l);
518 noauth_addrs = wp;
519 return 1;
520}
521
522
523/*
524 * set_permitted_number - set remote telephone number(s) that may connect.
525 */
526static int
527set_permitted_number(argv)
528 char **argv;
529{
530 char *number = *argv;
531 int l = strlen(number) + 1;
532 struct wordlist *wp;
533
534 wp = (struct wordlist *) malloc(sizeof(struct wordlist) + l);
535 if (wp == NULL)
536 novm("allow-number argument");
537 wp->word = (char *) (wp + 1);
538 wp->next = permitted_numbers;
539 MEMCPY(wp->word, number, l);
540 permitted_numbers = wp;
541 return 1;
542}
543#endif
544
545/*
546 * An Open on LCP has requested a change from Dead to Establish phase.
547 */
548void link_required(ppp_pcb *pcb) {
549 LWIP_UNUSED_ARG(pcb);
550}
551
552#if 0
553/*
554 * Bring the link up to the point of being able to do ppp.
555 */
556void start_link(unit)
557 int unit;
558{
559 ppp_pcb *pcb = &ppp_pcb_list[unit];
560 char *msg;
561
562 status = EXIT_NEGOTIATION_FAILED;
563 new_phase(pcb, PPP_PHASE_SERIALCONN);
564
565 hungup = 0;
566 devfd = the_channel->connect();
567 msg = "Connect script failed";
568 if (devfd < 0)
569 goto fail;
570
571 /* set up the serial device as a ppp interface */
572 /*
573 * N.B. we used to do tdb_writelock/tdb_writeunlock around this
574 * (from establish_ppp to set_ifunit). However, we won't be
575 * doing the set_ifunit in multilink mode, which is the only time
576 * we need the atomicity that the tdb_writelock/tdb_writeunlock
577 * gives us. Thus we don't need the tdb_writelock/tdb_writeunlock.
578 */
579 fd_ppp = the_channel->establish_ppp(devfd);
580 msg = "ppp establishment failed";
581 if (fd_ppp < 0) {
582 status = EXIT_FATAL_ERROR;
583 goto disconnect;
584 }
585
586 if (!demand && ifunit >= 0)
587 set_ifunit(1);
588
589 /*
590 * Start opening the connection and wait for
591 * incoming events (reply, timeout, etc.).
592 */
593 if (ifunit >= 0)
594 ppp_notice(("Connect: %s <--> %s", ifname, ppp_devnam));
595 else
596 ppp_notice(("Starting negotiation on %s", ppp_devnam));
597 add_fd(fd_ppp);
598
599 new_phase(pcb, PPP_PHASE_ESTABLISH);
600
601 lcp_lowerup(pcb);
602 return;
603
605 new_phase(pcb, PPP_PHASE_DISCONNECT);
606 if (the_channel->disconnect)
607 the_channel->disconnect();
608
609 fail:
610 new_phase(pcb, PPP_PHASE_DEAD);
611 if (the_channel->cleanup)
612 (*the_channel->cleanup)();
613}
614#endif
615
616/*
617 * LCP has terminated the link; go to the Dead phase and take the
618 * physical layer down.
619 */
620void link_terminated(ppp_pcb *pcb) {
621 if (pcb->phase == PPP_PHASE_DEAD
622#ifdef HAVE_MULTILINK
623 || pcb->phase == PPP_PHASE_MASTER
624#endif /* HAVE_MULTILINK */
625 )
626 return;
627 new_phase(pcb, PPP_PHASE_DISCONNECT);
628
629#if 0 /* UNUSED */
630 if (pap_logout_hook) {
631 pap_logout_hook();
632 }
633 session_end(devnam);
634#endif /* UNUSED */
635
636 if (!doing_multilink) {
637 ppp_notice(("Connection terminated."));
638#if PPP_STATS_SUPPORT
639 print_link_stats();
640#endif /* PPP_STATS_SUPPORT */
641 } else
642 ppp_notice(("Link terminated."));
643
644 lcp_lowerdown(pcb);
645
646 ppp_link_terminated(pcb);
647#if 0
648 /*
649 * Delete pid files before disestablishing ppp. Otherwise it
650 * can happen that another pppd gets the same unit and then
651 * we delete its pid file.
652 */
653 if (!doing_multilink && !demand)
654 remove_pidfiles();
655
656 /*
657 * If we may want to bring the link up again, transfer
658 * the ppp unit back to the loopback. Set the
659 * real serial device back to its normal mode of operation.
660 */
661 if (fd_ppp >= 0) {
662 remove_fd(fd_ppp);
663 clean_check();
664 the_channel->disestablish_ppp(devfd);
665 if (doing_multilink)
666 mp_exit_bundle();
667 fd_ppp = -1;
668 }
669 if (!hungup)
670 lcp_lowerdown(pcb);
671 if (!doing_multilink && !demand)
672 script_unsetenv("IFNAME");
673
674 /*
675 * Run disconnector script, if requested.
676 * XXX we may not be able to do this if the line has hung up!
677 */
678 if (devfd >= 0 && the_channel->disconnect) {
679 the_channel->disconnect();
680 devfd = -1;
681 }
682 if (the_channel->cleanup)
683 (*the_channel->cleanup)();
684
685 if (doing_multilink && multilink_master) {
686 if (!bundle_terminating)
687 new_phase(pcb, PPP_PHASE_MASTER);
688 else
689 mp_bundle_terminated();
690 } else
691 new_phase(pcb, PPP_PHASE_DEAD);
692#endif
693}
694
695/*
696 * LCP has gone down; it will either die or try to re-establish.
697 */
698void link_down(ppp_pcb *pcb) {
699#if PPP_NOTIFY
700 notify(link_down_notifier, 0);
701#endif /* PPP_NOTIFY */
702
703 if (!doing_multilink) {
704 upper_layers_down(pcb);
705 if (pcb->phase != PPP_PHASE_DEAD
706#ifdef HAVE_MULTILINK
707 && pcb->phase != PPP_PHASE_MASTER
708#endif /* HAVE_MULTILINK */
709 )
710 new_phase(pcb, PPP_PHASE_ESTABLISH);
711 }
712 /* XXX if doing_multilink, should do something to stop
713 network-layer traffic on the link */
714}
715
716void upper_layers_down(ppp_pcb *pcb) {
717 int i;
718 const struct protent *protp;
719
720 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
721 if (protp->protocol != PPP_LCP && protp->lowerdown != NULL)
722 (*protp->lowerdown)(pcb);
723 if (protp->protocol < 0xC000 && protp->close != NULL)
724 (*protp->close)(pcb, "LCP down");
725 }
726 pcb->num_np_open = 0;
727 pcb->num_np_up = 0;
728}
729
730/*
731 * The link is established.
732 * Proceed to the Dead, Authenticate or Network phase as appropriate.
733 */
734void link_established(ppp_pcb *pcb) {
735#if PPP_AUTH_SUPPORT
736 int auth;
737#if PPP_SERVER
738#if PAP_SUPPORT
739 lcp_options *wo = &pcb->lcp_wantoptions;
740#endif /* PAP_SUPPORT */
741 lcp_options *go = &pcb->lcp_gotoptions;
742#endif /* PPP_SERVER */
743 lcp_options *ho = &pcb->lcp_hisoptions;
744#endif /* PPP_AUTH_SUPPORT */
745 int i;
746 const struct protent *protp;
747
748 /*
749 * Tell higher-level protocols that LCP is up.
750 */
751 if (!doing_multilink) {
752 for (i = 0; (protp = protocols[i]) != NULL; ++i)
753 if (protp->protocol != PPP_LCP
754 && protp->lowerup != NULL)
755 (*protp->lowerup)(pcb);
756 }
757
758#if PPP_AUTH_SUPPORT
759#if PPP_SERVER
760#if PPP_ALLOWED_ADDRS
761 if (!auth_required && noauth_addrs != NULL)
762 set_allowed_addrs(unit, NULL, NULL);
763#endif /* PPP_ALLOWED_ADDRS */
764
765 if (pcb->settings.auth_required && !(0
766#if PAP_SUPPORT
767 || go->neg_upap
768#endif /* PAP_SUPPORT */
769#if CHAP_SUPPORT
770 || go->neg_chap
771#endif /* CHAP_SUPPORT */
772#if EAP_SUPPORT
773 || go->neg_eap
774#endif /* EAP_SUPPORT */
775 )) {
776
777#if PPP_ALLOWED_ADDRS
778 /*
779 * We wanted the peer to authenticate itself, and it refused:
780 * if we have some address(es) it can use without auth, fine,
781 * otherwise treat it as though it authenticated with PAP using
782 * a username of "" and a password of "". If that's not OK,
783 * boot it out.
784 */
785 if (noauth_addrs != NULL) {
786 set_allowed_addrs(unit, NULL, NULL);
787 } else
788#endif /* PPP_ALLOWED_ADDRS */
789 if (!pcb->settings.null_login
790#if PAP_SUPPORT
791 || !wo->neg_upap
792#endif /* PAP_SUPPORT */
793 ) {
794 ppp_warn(("peer refused to authenticate: terminating link"));
795#if 0 /* UNUSED */
796 status = EXIT_PEER_AUTH_FAILED;
797#endif /* UNUSED */
798 pcb->err_code = PPPERR_AUTHFAIL;
799 lcp_close(pcb, "peer refused to authenticate");
800 return;
801 }
802 }
803#endif /* PPP_SERVER */
804
805 new_phase(pcb, PPP_PHASE_AUTHENTICATE);
806 auth = 0;
807#if PPP_SERVER
808#if EAP_SUPPORT
809 if (go->neg_eap) {
810 eap_authpeer(pcb, PPP_OUR_NAME);
811 auth |= EAP_PEER;
812 } else
813#endif /* EAP_SUPPORT */
814#if CHAP_SUPPORT
815 if (go->neg_chap) {
816 chap_auth_peer(pcb, PPP_OUR_NAME, CHAP_DIGEST(go->chap_mdtype));
817 auth |= CHAP_PEER;
818 } else
819#endif /* CHAP_SUPPORT */
820#if PAP_SUPPORT
821 if (go->neg_upap) {
822 upap_authpeer(pcb);
823 auth |= PAP_PEER;
824 } else
825#endif /* PAP_SUPPORT */
826 {}
827#endif /* PPP_SERVER */
828
829#if EAP_SUPPORT
830 if (ho->neg_eap) {
831 eap_authwithpeer(pcb, pcb->settings.user);
832 auth |= EAP_WITHPEER;
833 } else
834#endif /* EAP_SUPPORT */
835#if CHAP_SUPPORT
836 if (ho->neg_chap) {
837 chap_auth_with_peer(pcb, pcb->settings.user, CHAP_DIGEST(ho->chap_mdtype));
838 auth |= CHAP_WITHPEER;
839 } else
840#endif /* CHAP_SUPPORT */
841#if PAP_SUPPORT
842 if (ho->neg_upap) {
843 upap_authwithpeer(pcb, pcb->settings.user, pcb->settings.passwd);
844 auth |= PAP_WITHPEER;
845 } else
846#endif /* PAP_SUPPORT */
847 {}
848
849 pcb->auth_pending = auth;
850 pcb->auth_done = 0;
851
852 if (!auth)
853#endif /* PPP_AUTH_SUPPORT */
854 network_phase(pcb);
855}
856
857/*
858 * Proceed to the network phase.
859 */
860static void network_phase(ppp_pcb *pcb) {
861#if CBCP_SUPPORT
862 ppp_pcb *pcb = &ppp_pcb_list[unit];
863#endif
864#if 0 /* UNUSED */
865 lcp_options *go = &lcp_gotoptions[unit];
866#endif /* UNUSED */
867
868#if 0 /* UNUSED */
869 /* Log calling number. */
870 if (*remote_number)
871 ppp_notice(("peer from calling number %q authorized", remote_number));
872#endif /* UNUSED */
873
874#if PPP_NOTIFY
875 /*
876 * If the peer had to authenticate, notify it now.
877 */
878 if (0
879#if CHAP_SUPPORT
880 || go->neg_chap
881#endif /* CHAP_SUPPORT */
882#if PAP_SUPPORT
883 || go->neg_upap
884#endif /* PAP_SUPPORT */
885#if EAP_SUPPORT
886 || go->neg_eap
887#endif /* EAP_SUPPORT */
888 ) {
889 notify(auth_up_notifier, 0);
890 }
891#endif /* PPP_NOTIFY */
892
893#if CBCP_SUPPORT
894 /*
895 * If we negotiated callback, do it now.
896 */
897 if (go->neg_cbcp) {
898 new_phase(pcb, PPP_PHASE_CALLBACK);
899 (*cbcp_protent.open)(pcb);
900 return;
901 }
902#endif
903
904#if PPP_OPTIONS
905 /*
906 * Process extra options from the secrets file
907 */
908 if (extra_options) {
909 options_from_list(extra_options, 1);
910 free_wordlist(extra_options);
911 extra_options = 0;
912 }
913#endif /* PPP_OPTIONS */
914 start_networks(pcb);
915}
916
917void start_networks(ppp_pcb *pcb) {
918#if CCP_SUPPORT || ECP_SUPPORT
919 int i;
920 const struct protent *protp;
921#endif /* CCP_SUPPORT || ECP_SUPPORT */
922
923 new_phase(pcb, PPP_PHASE_NETWORK);
924
925#ifdef HAVE_MULTILINK
926 if (multilink) {
927 if (mp_join_bundle()) {
928 if (multilink_join_hook)
929 (*multilink_join_hook)();
930 if (updetach && !nodetach)
931 detach();
932 return;
933 }
934 }
935#endif /* HAVE_MULTILINK */
936
937#ifdef PPP_FILTER
938 if (!demand)
939 set_filters(&pass_filter, &active_filter);
940#endif
941#if CCP_SUPPORT || ECP_SUPPORT
942 /* Start CCP and ECP */
943 for (i = 0; (protp = protocols[i]) != NULL; ++i)
944 if (
945 (0
946#if ECP_SUPPORT
947 || protp->protocol == PPP_ECP
948#endif /* ECP_SUPPORT */
949#if CCP_SUPPORT
950 || protp->protocol == PPP_CCP
951#endif /* CCP_SUPPORT */
952 )
953 && protp->open != NULL)
954 (*protp->open)(pcb);
955#endif /* CCP_SUPPORT || ECP_SUPPORT */
956
957 /*
958 * Bring up other network protocols iff encryption is not required.
959 */
960 if (1
961#if ECP_SUPPORT
962 && !ecp_gotoptions[unit].required
963#endif /* ECP_SUPPORT */
964#if MPPE_SUPPORT
965 && !pcb->ccp_gotoptions.mppe
966#endif /* MPPE_SUPPORT */
967 )
968 continue_networks(pcb);
969}
970
971void continue_networks(ppp_pcb *pcb) {
972 int i;
973 const struct protent *protp;
974
975 /*
976 * Start the "real" network protocols.
977 */
978 for (i = 0; (protp = protocols[i]) != NULL; ++i)
979 if (protp->protocol < 0xC000
980#if CCP_SUPPORT
981 && protp->protocol != PPP_CCP
982#endif /* CCP_SUPPORT */
983#if ECP_SUPPORT
984 && protp->protocol != PPP_ECP
985#endif /* ECP_SUPPORT */
986 && protp->open != NULL) {
987 (*protp->open)(pcb);
988 ++pcb->num_np_open;
989 }
990
991 if (pcb->num_np_open == 0)
992 /* nothing to do */
993 lcp_close(pcb, "No network protocols running");
994}
995
996#if PPP_AUTH_SUPPORT
997#if PPP_SERVER
998/*
999 * auth_check_passwd - Check the user name and passwd against configuration.
1000 *
1001 * returns:
1002 * 0: Authentication failed.
1003 * 1: Authentication succeeded.
1004 * In either case, msg points to an appropriate message and msglen to the message len.
1005 */
1006int auth_check_passwd(ppp_pcb *pcb, char *auser, unsigned int userlen, char *apasswd, unsigned int passwdlen, const char **msg, int *msglen) {
1007 size_t secretuserlen;
1008 size_t secretpasswdlen;
1009
1010 if (pcb->settings.user && pcb->settings.passwd) {
1011 secretuserlen = strlen(pcb->settings.user);
1012 secretpasswdlen = strlen(pcb->settings.passwd);
1013 if (secretuserlen == userlen
1014 && secretpasswdlen == passwdlen
1015 && !memcmp(auser, pcb->settings.user, userlen)
1016 && !memcmp(apasswd, pcb->settings.passwd, passwdlen) ) {
1017 *msg = "Login ok";
1018 *msglen = sizeof("Login ok")-1;
1019 return 1;
1020 }
1021 }
1022
1023 *msg = "Login incorrect";
1024 *msglen = sizeof("Login incorrect")-1;
1025 return 0;
1026}
1027
1028/*
1029 * The peer has failed to authenticate himself using `protocol'.
1030 */
1031void auth_peer_fail(ppp_pcb *pcb, int protocol) {
1033 /*
1034 * Authentication failure: take the link down
1035 */
1036#if 0 /* UNUSED */
1037 status = EXIT_PEER_AUTH_FAILED;
1038#endif /* UNUSED */
1039 pcb->err_code = PPPERR_AUTHFAIL;
1040 lcp_close(pcb, "Authentication failed");
1041}
1042
1043/*
1044 * The peer has been successfully authenticated using `protocol'.
1045 */
1046void auth_peer_success(ppp_pcb *pcb, int protocol, int prot_flavor, const char *name, int namelen) {
1047 int bit;
1048#ifndef HAVE_MULTILINK
1051#endif /* HAVE_MULTILINK */
1052 LWIP_UNUSED_ARG(prot_flavor); /* if CHAP_SUPPORT is disabled */
1053
1054 switch (protocol) {
1055#if CHAP_SUPPORT
1056 case PPP_CHAP:
1057 bit = CHAP_PEER;
1058 switch (prot_flavor) {
1059 case CHAP_MD5:
1060 bit |= CHAP_MD5_PEER;
1061 break;
1062#if MSCHAP_SUPPORT
1063 case CHAP_MICROSOFT:
1064 bit |= CHAP_MS_PEER;
1065 break;
1066 case CHAP_MICROSOFT_V2:
1067 bit |= CHAP_MS2_PEER;
1068 break;
1069#endif /* MSCHAP_SUPPORT */
1070 default:
1071 break;
1072 }
1073 break;
1074#endif /* CHAP_SUPPORT */
1075#if PAP_SUPPORT
1076 case PPP_PAP:
1077 bit = PAP_PEER;
1078 break;
1079#endif /* PAP_SUPPORT */
1080#if EAP_SUPPORT
1081 case PPP_EAP:
1082 bit = EAP_PEER;
1083 break;
1084#endif /* EAP_SUPPORT */
1085 default:
1086 ppp_warn(("auth_peer_success: unknown protocol %x", protocol));
1087 return;
1088 }
1089
1090#ifdef HAVE_MULTILINK
1091 /*
1092 * Save the authenticated name of the peer for later.
1093 */
1094 if (namelen > (int)sizeof(pcb->peer_authname) - 1)
1095 namelen = (int)sizeof(pcb->peer_authname) - 1;
1096 MEMCPY(pcb->peer_authname, name, namelen);
1097 pcb->peer_authname[namelen] = 0;
1098#endif /* HAVE_MULTILINK */
1099#if 0 /* UNUSED */
1100 script_setenv("PEERNAME", , 0);
1101#endif /* UNUSED */
1102
1103 /* Save the authentication method for later. */
1104 pcb->auth_done |= bit;
1105
1106 /*
1107 * If there is no more authentication still to be done,
1108 * proceed to the network (or callback) phase.
1109 */
1110 if ((pcb->auth_pending &= ~bit) == 0)
1111 network_phase(pcb);
1112}
1113#endif /* PPP_SERVER */
1114
1115/*
1116 * We have failed to authenticate ourselves to the peer using `protocol'.
1117 */
1118void auth_withpeer_fail(ppp_pcb *pcb, int protocol) {
1120 /*
1121 * We've failed to authenticate ourselves to our peer.
1122 *
1123 * Some servers keep sending CHAP challenges, but there
1124 * is no point in persisting without any way to get updated
1125 * authentication secrets.
1126 *
1127 * He'll probably take the link down, and there's not much
1128 * we can do except wait for that.
1129 */
1130 pcb->err_code = PPPERR_AUTHFAIL;
1131 lcp_close(pcb, "Failed to authenticate ourselves to peer");
1132}
1133
1134/*
1135 * We have successfully authenticated ourselves with the peer using `protocol'.
1136 */
1137void auth_withpeer_success(ppp_pcb *pcb, int protocol, int prot_flavor) {
1138 int bit;
1139 const char *prot = "";
1140 LWIP_UNUSED_ARG(prot_flavor); /* if CHAP_SUPPORT is disabled */
1141
1142 switch (protocol) {
1143#if CHAP_SUPPORT
1144 case PPP_CHAP:
1145 bit = CHAP_WITHPEER;
1146 prot = "CHAP";
1147 switch (prot_flavor) {
1148 case CHAP_MD5:
1149 bit |= CHAP_MD5_WITHPEER;
1150 break;
1151#if MSCHAP_SUPPORT
1152 case CHAP_MICROSOFT:
1153 bit |= CHAP_MS_WITHPEER;
1154 break;
1155 case CHAP_MICROSOFT_V2:
1156 bit |= CHAP_MS2_WITHPEER;
1157 break;
1158#endif /* MSCHAP_SUPPORT */
1159 default:
1160 break;
1161 }
1162 break;
1163#endif /* CHAP_SUPPORT */
1164#if PAP_SUPPORT
1165 case PPP_PAP:
1166 bit = PAP_WITHPEER;
1167 prot = "PAP";
1168 break;
1169#endif /* PAP_SUPPORT */
1170#if EAP_SUPPORT
1171 case PPP_EAP:
1172 bit = EAP_WITHPEER;
1173 prot = "EAP";
1174 break;
1175#endif /* EAP_SUPPORT */
1176 default:
1177 ppp_warn(("auth_withpeer_success: unknown protocol %x", protocol));
1178 bit = 0;
1179 /* no break */
1180 }
1181
1182 ppp_notice(("%s authentication succeeded", prot));
1183
1184 /* Save the authentication method for later. */
1185 pcb->auth_done |= bit;
1186
1187 /*
1188 * If there is no more authentication still being done,
1189 * proceed to the network (or callback) phase.
1190 */
1191 if ((pcb->auth_pending &= ~bit) == 0)
1192 network_phase(pcb);
1193}
1194#endif /* PPP_AUTH_SUPPORT */
1195
1196
1197/*
1198 * np_up - a network protocol has come up.
1199 */
1200void np_up(ppp_pcb *pcb, int proto) {
1201#if PPP_IDLETIMELIMIT
1202 int tlim;
1203#endif /* PPP_IDLETIMELIMIT */
1205
1206 if (pcb->num_np_up == 0) {
1207 /*
1208 * At this point we consider that the link has come up successfully.
1209 */
1210 new_phase(pcb, PPP_PHASE_RUNNING);
1211
1212#if PPP_IDLETIMELIMIT
1213#if 0 /* UNUSED */
1214 if (idle_time_hook != 0)
1215 tlim = (*idle_time_hook)(NULL);
1216 else
1217#endif /* UNUSED */
1218 tlim = pcb->settings.idle_time_limit;
1219 if (tlim > 0)
1220 TIMEOUT(check_idle, (void*)pcb, tlim);
1221#endif /* PPP_IDLETIMELIMIT */
1222
1223#if PPP_MAXCONNECT
1224 /*
1225 * Set a timeout to close the connection once the maximum
1226 * connect time has expired.
1227 */
1228 if (pcb->settings.maxconnect > 0)
1229 TIMEOUT(connect_time_expired, (void*)pcb, pcb->settings.maxconnect);
1230#endif /* PPP_MAXCONNECT */
1231
1232#ifdef MAXOCTETS
1233 if (maxoctets > 0)
1234 TIMEOUT(check_maxoctets, NULL, maxoctets_timeout);
1235#endif
1236
1237#if 0 /* Unused */
1238 /*
1239 * Detach now, if the updetach option was given.
1240 */
1241 if (updetach && !nodetach)
1242 detach();
1243#endif /* Unused */
1244 }
1245 ++pcb->num_np_up;
1246}
1247
1248/*
1249 * np_down - a network protocol has gone down.
1250 */
1251void np_down(ppp_pcb *pcb, int proto) {
1253 if (--pcb->num_np_up == 0) {
1254#if PPP_IDLETIMELIMIT
1255 UNTIMEOUT(check_idle, (void*)pcb);
1256#endif /* PPP_IDLETIMELIMIT */
1257#if PPP_MAXCONNECT
1258 UNTIMEOUT(connect_time_expired, NULL);
1259#endif /* PPP_MAXCONNECT */
1260#ifdef MAXOCTETS
1261 UNTIMEOUT(check_maxoctets, NULL);
1262#endif
1263 new_phase(pcb, PPP_PHASE_NETWORK);
1264 }
1265}
1266
1267/*
1268 * np_finished - a network protocol has finished using the link.
1269 */
1270void np_finished(ppp_pcb *pcb, int proto) {
1272 if (--pcb->num_np_open <= 0) {
1273 /* no further use for the link: shut up shop. */
1274 lcp_close(pcb, "No network protocols running");
1275 }
1276}
1277
1278#ifdef MAXOCTETS
1279static void
1280check_maxoctets(arg)
1281 void *arg;
1282{
1283#if PPP_STATS_SUPPORT
1284 unsigned int used;
1285
1286 update_link_stats(ifunit);
1287 link_stats_valid=0;
1288
1289 switch(maxoctets_dir) {
1290 case PPP_OCTETS_DIRECTION_IN:
1291 used = link_stats.bytes_in;
1292 break;
1293 case PPP_OCTETS_DIRECTION_OUT:
1294 used = link_stats.bytes_out;
1295 break;
1296 case PPP_OCTETS_DIRECTION_MAXOVERAL:
1297 case PPP_OCTETS_DIRECTION_MAXSESSION:
1298 used = (link_stats.bytes_in > link_stats.bytes_out) ? link_stats.bytes_in : link_stats.bytes_out;
1299 break;
1300 default:
1301 used = link_stats.bytes_in+link_stats.bytes_out;
1302 break;
1303 }
1304 if (used > maxoctets) {
1305 ppp_notice(("Traffic limit reached. Limit: %u Used: %u", maxoctets, used));
1306 status = EXIT_TRAFFIC_LIMIT;
1307 lcp_close(pcb, "Traffic limit");
1308#if 0 /* UNUSED */
1309 need_holdoff = 0;
1310#endif /* UNUSED */
1311 } else {
1312 TIMEOUT(check_maxoctets, NULL, maxoctets_timeout);
1313 }
1314#endif /* PPP_STATS_SUPPORT */
1315}
1316#endif /* MAXOCTETS */
1317
1318#if PPP_IDLETIMELIMIT
1319/*
1320 * check_idle - check whether the link has been idle for long
1321 * enough that we can shut it down.
1322 */
1323static void check_idle(void *arg) {
1324 ppp_pcb *pcb = (ppp_pcb*)arg;
1325 struct ppp_idle idle;
1326 time_t itime;
1327 int tlim;
1328
1329 if (!get_idle_time(pcb, &idle))
1330 return;
1331#if 0 /* UNUSED */
1332 if (idle_time_hook != 0) {
1333 tlim = idle_time_hook(&idle);
1334 } else {
1335#endif /* UNUSED */
1336 itime = LWIP_MIN(idle.xmit_idle, idle.recv_idle);
1337 tlim = pcb->settings.idle_time_limit - itime;
1338#if 0 /* UNUSED */
1339 }
1340#endif /* UNUSED */
1341 if (tlim <= 0) {
1342 /* link is idle: shut it down. */
1343 ppp_notice(("Terminating connection due to lack of activity."));
1344 pcb->err_code = PPPERR_IDLETIMEOUT;
1345 lcp_close(pcb, "Link inactive");
1346#if 0 /* UNUSED */
1347 need_holdoff = 0;
1348#endif /* UNUSED */
1349 } else {
1350 TIMEOUT(check_idle, (void*)pcb, tlim);
1351 }
1352}
1353#endif /* PPP_IDLETIMELIMIT */
1354
1355#if PPP_MAXCONNECT
1356/*
1357 * connect_time_expired - log a message and close the connection.
1358 */
1359static void connect_time_expired(void *arg) {
1360 ppp_pcb *pcb = (ppp_pcb*)arg;
1361 ppp_info(("Connect time expired"));
1362 pcb->err_code = PPPERR_CONNECTTIME;
1363 lcp_close(pcb, "Connect time expired"); /* Close connection */
1364}
1365#endif /* PPP_MAXCONNECT */
1366
1367#if PPP_OPTIONS
1368/*
1369 * auth_check_options - called to check authentication options.
1370 */
1371void
1372auth_check_options()
1373{
1374 lcp_options *wo = &lcp_wantoptions[0];
1375 int can_auth;
1376 int lacks_ip;
1377
1378 /* Default our_name to hostname, and user to our_name */
1379 if (our_name[0] == 0 || usehostname)
1380 strlcpy(our_name, hostname, sizeof(our_name));
1381 /* If a blank username was explicitly given as an option, trust
1382 the user and don't use our_name */
1383 if (ppp_settings.user[0] == 0 && !explicit_user)
1384 strlcpy(ppp_settings.user, our_name, sizeof(ppp_settings.user));
1385
1386 /*
1387 * If we have a default route, require the peer to authenticate
1388 * unless the noauth option was given or the real user is root.
1389 */
1390 if (!auth_required && !allow_any_ip && have_route_to(0) && !privileged) {
1391 auth_required = 1;
1392 default_auth = 1;
1393 }
1394
1395#if CHAP_SUPPORT
1396 /* If we selected any CHAP flavors, we should probably negotiate it. :-) */
1397 if (wo->chap_mdtype)
1398 wo->neg_chap = 1;
1399#endif /* CHAP_SUPPORT */
1400
1401 /* If authentication is required, ask peer for CHAP, PAP, or EAP. */
1402 if (auth_required) {
1403 allow_any_ip = 0;
1404 if (1
1405#if CHAP_SUPPORT
1406 && !wo->neg_chap
1407#endif /* CHAP_SUPPORT */
1408#if PAP_SUPPORT
1409 && !wo->neg_upap
1410#endif /* PAP_SUPPORT */
1411#if EAP_SUPPORT
1412 && !wo->neg_eap
1413#endif /* EAP_SUPPORT */
1414 ) {
1415#if CHAP_SUPPORT
1416 wo->neg_chap = CHAP_MDTYPE_SUPPORTED != MDTYPE_NONE;
1417 wo->chap_mdtype = CHAP_MDTYPE_SUPPORTED;
1418#endif /* CHAP_SUPPORT */
1419#if PAP_SUPPORT
1420 wo->neg_upap = 1;
1421#endif /* PAP_SUPPORT */
1422#if EAP_SUPPORT
1423 wo->neg_eap = 1;
1424#endif /* EAP_SUPPORT */
1425 }
1426 } else {
1427#if CHAP_SUPPORT
1428 wo->neg_chap = 0;
1429 wo->chap_mdtype = MDTYPE_NONE;
1430#endif /* CHAP_SUPPORT */
1431#if PAP_SUPPORT
1432 wo->neg_upap = 0;
1433#endif /* PAP_SUPPORT */
1434#if EAP_SUPPORT
1435 wo->neg_eap = 0;
1436#endif /* EAP_SUPPORT */
1437 }
1438
1439 /*
1440 * Check whether we have appropriate secrets to use
1441 * to authenticate the peer. Note that EAP can authenticate by way
1442 * of a CHAP-like exchanges as well as SRP.
1443 */
1444 lacks_ip = 0;
1445#if PAP_SUPPORT
1446 can_auth = wo->neg_upap && (uselogin || have_pap_secret(&lacks_ip));
1447#else
1448 can_auth = 0;
1449#endif /* PAP_SUPPORT */
1450 if (!can_auth && (0
1451#if CHAP_SUPPORT
1452 || wo->neg_chap
1453#endif /* CHAP_SUPPORT */
1454#if EAP_SUPPORT
1455 || wo->neg_eap
1456#endif /* EAP_SUPPORT */
1457 )) {
1458#if CHAP_SUPPORT
1459 can_auth = have_chap_secret((explicit_remote? remote_name: NULL),
1460 our_name, 1, &lacks_ip);
1461#else
1462 can_auth = 0;
1463#endif
1464 }
1465 if (!can_auth
1466#if EAP_SUPPORT
1467 && wo->neg_eap
1468#endif /* EAP_SUPPORT */
1469 ) {
1470 can_auth = have_srp_secret((explicit_remote? remote_name: NULL),
1471 our_name, 1, &lacks_ip);
1472 }
1473
1474 if (auth_required && !can_auth && noauth_addrs == NULL) {
1475 if (default_auth) {
1476 option_error(
1477"By default the remote system is required to authenticate itself");
1478 option_error(
1479"(because this system has a default route to the internet)");
1480 } else if (explicit_remote)
1481 option_error(
1482"The remote system (%s) is required to authenticate itself",
1483 remote_name);
1484 else
1485 option_error(
1486"The remote system is required to authenticate itself");
1487 option_error(
1488"but I couldn't find any suitable secret (password) for it to use to do so.");
1489 if (lacks_ip)
1490 option_error(
1491"(None of the available passwords would let it use an IP address.)");
1492
1493 exit(1);
1494 }
1495
1496 /*
1497 * Early check for remote number authorization.
1498 */
1499 if (!auth_number()) {
1500 ppp_warn(("calling number %q is not authorized", remote_number));
1501 exit(EXIT_CNID_AUTH_FAILED);
1502 }
1503}
1504#endif /* PPP_OPTIONS */
1505
1506#if 0 /* UNUSED */
1507/*
1508 * auth_reset - called when LCP is starting negotiations to recheck
1509 * authentication options, i.e. whether we have appropriate secrets
1510 * to use for authenticating ourselves and/or the peer.
1511 */
1512void
1513auth_reset(unit)
1514 int unit;
1515{
1516 lcp_options *go = &lcp_gotoptions[unit];
1517 lcp_options *ao = &lcp_allowoptions[unit];
1518 int hadchap;
1519
1520 hadchap = -1;
1521 ao->neg_upap = !refuse_pap && (passwd[0] != 0 || get_pap_passwd(NULL));
1522 ao->neg_chap = (!refuse_chap || !refuse_mschap || !refuse_mschap_v2)
1523 && (passwd[0] != 0 ||
1524 (hadchap = have_chap_secret(user, (explicit_remote? remote_name:
1525 NULL), 0, NULL)));
1526 ao->neg_eap = !refuse_eap && (
1527 passwd[0] != 0 ||
1528 (hadchap == 1 || (hadchap == -1 && have_chap_secret(user,
1529 (explicit_remote? remote_name: NULL), 0, NULL))) ||
1530 have_srp_secret(user, (explicit_remote? remote_name: NULL), 0, NULL));
1531
1532 hadchap = -1;
1533 if (go->neg_upap && !uselogin && !have_pap_secret(NULL))
1534 go->neg_upap = 0;
1535 if (go->neg_chap) {
1536 if (!(hadchap = have_chap_secret((explicit_remote? remote_name: NULL),
1537 our_name, 1, NULL)))
1538 go->neg_chap = 0;
1539 }
1540 if (go->neg_eap &&
1541 (hadchap == 0 || (hadchap == -1 &&
1542 !have_chap_secret((explicit_remote? remote_name: NULL), our_name,
1543 1, NULL))) &&
1544 !have_srp_secret((explicit_remote? remote_name: NULL), our_name, 1,
1545 NULL))
1546 go->neg_eap = 0;
1547}
1548
1549/*
1550 * check_passwd - Check the user name and passwd against the PAP secrets
1551 * file. If requested, also check against the system password database,
1552 * and login the user if OK.
1553 *
1554 * returns:
1555 * UPAP_AUTHNAK: Authentication failed.
1556 * UPAP_AUTHACK: Authentication succeeded.
1557 * In either case, msg points to an appropriate message.
1558 */
1559int
1560check_passwd(unit, auser, userlen, apasswd, passwdlen, msg)
1561 int unit;
1562 char *auser;
1563 int userlen;
1564 char *apasswd;
1565 int passwdlen;
1566 char **msg;
1567{
1568 return UPAP_AUTHNAK;
1569 int ret;
1570 char *filename;
1571 FILE *f;
1572 struct wordlist *addrs = NULL, *opts = NULL;
1573 char passwd[256], user[256];
1574 char secret[MAXWORDLEN];
1575 static int attempts = 0;
1576
1577 /*
1578 * Make copies of apasswd and auser, then null-terminate them.
1579 * If there are unprintable characters in the password, make
1580 * them visible.
1581 */
1582 slprintf(ppp_settings.passwd, sizeof(ppp_settings.passwd), "%.*v", passwdlen, apasswd);
1583 slprintf(ppp_settings.user, sizeof(ppp_settings.user), "%.*v", userlen, auser);
1584 *msg = "";
1585
1586 /*
1587 * Check if a plugin wants to handle this.
1588 */
1589 if (pap_auth_hook) {
1590 ret = (*pap_auth_hook)(ppp_settings.user, ppp_settings.passwd, msg, &addrs, &opts);
1591 if (ret >= 0) {
1592 /* note: set_allowed_addrs() saves opts (but not addrs):
1593 don't free it! */
1594 if (ret)
1595 set_allowed_addrs(unit, addrs, opts);
1596 else if (opts != 0)
1597 free_wordlist(opts);
1598 if (addrs != 0)
1599 free_wordlist(addrs);
1600 BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd));
1601 return ret? UPAP_AUTHACK: UPAP_AUTHNAK;
1602 }
1603 }
1604
1605 /*
1606 * Open the file of pap secrets and scan for a suitable secret
1607 * for authenticating this user.
1608 */
1609 filename = _PATH_UPAPFILE;
1610 addrs = opts = NULL;
1611 ret = UPAP_AUTHNAK;
1612 f = fopen(filename, "r");
1613 if (f == NULL) {
1614 ppp_error(("Can't open PAP password file %s: %m", filename));
1615
1616 } else {
1618 if (scan_authfile(f, ppp_settings.user, our_name, secret, &addrs, &opts, filename, 0) < 0) {
1619 ppp_warn(("no PAP secret found for %s", user));
1620 } else {
1621 /*
1622 * If the secret is "@login", it means to check
1623 * the password against the login database.
1624 */
1625 int login_secret = strcmp(secret, "@login") == 0;
1626 ret = UPAP_AUTHACK;
1627 if (uselogin || login_secret) {
1628 /* login option or secret is @login */
1629 if (session_full(ppp_settings.user, ppp_settings.passwd, devnam, msg) == 0) {
1630 ret = UPAP_AUTHNAK;
1631 }
1632 } else if (session_mgmt) {
1633 if (session_check(ppp_settings.user, NULL, devnam, NULL) == 0) {
1634 ppp_warn(("Peer %q failed PAP Session verification", user));
1635 ret = UPAP_AUTHNAK;
1636 }
1637 }
1638 if (secret[0] != 0 && !login_secret) {
1639 /* password given in pap-secrets - must match */
1640 if ((cryptpap || strcmp(ppp_settings.passwd, secret) != 0)
1641 && strcmp(crypt(ppp_settings.passwd, secret), secret) != 0)
1642 ret = UPAP_AUTHNAK;
1643 }
1644 }
1645 fclose(f);
1646 }
1647
1648 if (ret == UPAP_AUTHNAK) {
1649 if (**msg == 0)
1650 *msg = "Login incorrect";
1651 /*
1652 * XXX can we ever get here more than once??
1653 * Frustrate passwd stealer programs.
1654 * Allow 10 tries, but start backing off after 3 (stolen from login).
1655 * On 10'th, drop the connection.
1656 */
1657 if (attempts++ >= 10) {
1658 ppp_warn(("%d LOGIN FAILURES ON %s, %s", attempts, devnam, user));
1659 lcp_close(pcb, "login failed");
1660 }
1661 if (attempts > 3)
1662 sleep((u_int) (attempts - 3) * 5);
1663 if (opts != NULL)
1664 free_wordlist(opts);
1665
1666 } else {
1667 attempts = 0; /* Reset count */
1668 if (**msg == 0)
1669 *msg = "Login ok";
1670 set_allowed_addrs(unit, addrs, opts);
1671 }
1672
1673 if (addrs != NULL)
1674 free_wordlist(addrs);
1675 BZERO(ppp_settings.passwd, sizeof(ppp_settings.passwd));
1676 BZERO(secret, sizeof(secret));
1677
1678 return ret;
1679}
1680
1681/*
1682 * null_login - Check if a username of "" and a password of "" are
1683 * acceptable, and iff so, set the list of acceptable IP addresses
1684 * and return 1.
1685 */
1686static int
1687null_login(unit)
1688 int unit;
1689{
1690 char *filename;
1691 FILE *f;
1692 int i, ret;
1693 struct wordlist *addrs, *opts;
1694 char secret[MAXWORDLEN];
1695
1696 /*
1697 * Check if a plugin wants to handle this.
1698 */
1699 ret = -1;
1700 if (null_auth_hook)
1701 ret = (*null_auth_hook)(&addrs, &opts);
1702
1703 /*
1704 * Open the file of pap secrets and scan for a suitable secret.
1705 */
1706 if (ret <= 0) {
1707 filename = _PATH_UPAPFILE;
1708 addrs = NULL;
1709 f = fopen(filename, "r");
1710 if (f == NULL)
1711 return 0;
1713
1714 i = scan_authfile(f, "", our_name, secret, &addrs, &opts, filename, 0);
1715 ret = i >= 0 && secret[0] == 0;
1716 BZERO(secret, sizeof(secret));
1717 fclose(f);
1718 }
1719
1720 if (ret)
1721 set_allowed_addrs(unit, addrs, opts);
1722 else if (opts != 0)
1723 free_wordlist(opts);
1724 if (addrs != 0)
1725 free_wordlist(addrs);
1726
1727 return ret;
1728}
1729
1730/*
1731 * get_pap_passwd - get a password for authenticating ourselves with
1732 * our peer using PAP. Returns 1 on success, 0 if no suitable password
1733 * could be found.
1734 * Assumes passwd points to MAXSECRETLEN bytes of space (if non-null).
1735 */
1736static int
1737get_pap_passwd(passwd)
1738 char *passwd;
1739{
1740 char *filename;
1741 FILE *f;
1742 int ret;
1743 char secret[MAXWORDLEN];
1744
1745 /*
1746 * Check whether a plugin wants to supply this.
1747 */
1748 if (pap_passwd_hook) {
1749 ret = (*pap_passwd_hook)(ppp_settings,user, ppp_settings.passwd);
1750 if (ret >= 0)
1751 return ret;
1752 }
1753
1754 filename = _PATH_UPAPFILE;
1755 f = fopen(filename, "r");
1756 if (f == NULL)
1757 return 0;
1759 ret = scan_authfile(f, user,
1760 (remote_name[0]? remote_name: NULL),
1761 secret, NULL, NULL, filename, 0);
1762 fclose(f);
1763 if (ret < 0)
1764 return 0;
1765 if (passwd != NULL)
1766 strlcpy(passwd, secret, MAXSECRETLEN);
1767 BZERO(secret, sizeof(secret));
1768 return 1;
1769}
1770
1771/*
1772 * have_pap_secret - check whether we have a PAP file with any
1773 * secrets that we could possibly use for authenticating the peer.
1774 */
1775static int
1776have_pap_secret(lacks_ipp)
1777 int *lacks_ipp;
1778{
1779 FILE *f;
1780 int ret;
1781 char *filename;
1782 struct wordlist *addrs;
1783
1784 /* let the plugin decide, if there is one */
1785 if (pap_check_hook) {
1786 ret = (*pap_check_hook)();
1787 if (ret >= 0)
1788 return ret;
1789 }
1790
1791 filename = _PATH_UPAPFILE;
1792 f = fopen(filename, "r");
1793 if (f == NULL)
1794 return 0;
1795
1796 ret = scan_authfile(f, (explicit_remote? remote_name: NULL), our_name,
1797 NULL, &addrs, NULL, filename, 0);
1798 fclose(f);
1799 if (ret >= 0 && !some_ip_ok(addrs)) {
1800 if (lacks_ipp != 0)
1801 *lacks_ipp = 1;
1802 ret = -1;
1803 }
1804 if (addrs != 0)
1805 free_wordlist(addrs);
1806
1807 return ret >= 0;
1808}
1809
1810/*
1811 * have_chap_secret - check whether we have a CHAP file with a
1812 * secret that we could possibly use for authenticating `client'
1813 * on `server'. Either can be the null string, meaning we don't
1814 * know the identity yet.
1815 */
1816static int
1817have_chap_secret(client, server, need_ip, lacks_ipp)
1818 char *client;
1819 char *server;
1820 int need_ip;
1821 int *lacks_ipp;
1822{
1823 FILE *f;
1824 int ret;
1825 char *filename;
1826 struct wordlist *addrs;
1827
1828 if (chap_check_hook) {
1829 ret = (*chap_check_hook)();
1830 if (ret >= 0) {
1831 return ret;
1832 }
1833 }
1834
1835 filename = _PATH_CHAPFILE;
1836 f = fopen(filename, "r");
1837 if (f == NULL)
1838 return 0;
1839
1840 if (client != NULL && client[0] == 0)
1841 client = NULL;
1842 else if (server != NULL && server[0] == 0)
1843 server = NULL;
1844
1845 ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0);
1846 fclose(f);
1847 if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
1848 if (lacks_ipp != 0)
1849 *lacks_ipp = 1;
1850 ret = -1;
1851 }
1852 if (addrs != 0)
1853 free_wordlist(addrs);
1854
1855 return ret >= 0;
1856}
1857
1858/*
1859 * have_srp_secret - check whether we have a SRP file with a
1860 * secret that we could possibly use for authenticating `client'
1861 * on `server'. Either can be the null string, meaning we don't
1862 * know the identity yet.
1863 */
1864static int
1865have_srp_secret(client, server, need_ip, lacks_ipp)
1866 char *client;
1867 char *server;
1868 int need_ip;
1869 int *lacks_ipp;
1870{
1871 FILE *f;
1872 int ret;
1873 char *filename;
1874 struct wordlist *addrs;
1875
1876 filename = _PATH_SRPFILE;
1877 f = fopen(filename, "r");
1878 if (f == NULL)
1879 return 0;
1880
1881 if (client != NULL && client[0] == 0)
1882 client = NULL;
1883 else if (server != NULL && server[0] == 0)
1884 server = NULL;
1885
1886 ret = scan_authfile(f, client, server, NULL, &addrs, NULL, filename, 0);
1887 fclose(f);
1888 if (ret >= 0 && need_ip && !some_ip_ok(addrs)) {
1889 if (lacks_ipp != 0)
1890 *lacks_ipp = 1;
1891 ret = -1;
1892 }
1893 if (addrs != 0)
1894 free_wordlist(addrs);
1895
1896 return ret >= 0;
1897}
1898#endif /* UNUSED */
1899
1900#if PPP_AUTH_SUPPORT
1901/*
1902 * get_secret - open the CHAP secret file and return the secret
1903 * for authenticating the given client on the given server.
1904 * (We could be either client or server).
1905 */
1906int get_secret(ppp_pcb *pcb, const char *client, const char *server, char *secret, int *secret_len, int am_server) {
1907 size_t len;
1909 LWIP_UNUSED_ARG(am_server);
1910
1911 if (!client || !client[0] || !pcb->settings.user || !pcb->settings.passwd || strcmp(client, pcb->settings.user)) {
1912 return 0;
1913 }
1914
1915 len = strlen(pcb->settings.passwd);
1916 if (len > MAXSECRETLEN) {
1917 ppp_error(("Secret for %s on %s is too long", client, server));
1918 len = MAXSECRETLEN;
1919 }
1920
1921 MEMCPY(secret, pcb->settings.passwd, len);
1922 *secret_len = len;
1923 return 1;
1924
1925#if 0 /* UNUSED */
1926 FILE *f;
1927 int ret;
1928 size_t len;
1929 char *filename;
1930 struct wordlist *addrs, *opts;
1931 char secbuf[MAXWORDLEN];
1932 struct wordlist *addrs;
1933 addrs = NULL;
1934
1935 if (!am_server && ppp_settings.passwd[0] != 0) {
1936 strlcpy(secbuf, ppp_settings.passwd, sizeof(secbuf));
1937 } else if (!am_server && chap_passwd_hook) {
1938 if ( (*chap_passwd_hook)(client, secbuf) < 0) {
1939 ppp_error(("Unable to obtain CHAP password for %s on %s from plugin",
1940 client, server));
1941 return 0;
1942 }
1943 } else {
1944 filename = _PATH_CHAPFILE;
1945 addrs = NULL;
1946 secbuf[0] = 0;
1947
1948 f = fopen(filename, "r");
1949 if (f == NULL) {
1950 ppp_error(("Can't open chap secret file %s: %m", filename));
1951 return 0;
1952 }
1954
1955 ret = scan_authfile(f, client, server, secbuf, &addrs, &opts, filename, 0);
1956 fclose(f);
1957 if (ret < 0)
1958 return 0;
1959
1960 if (am_server)
1961 set_allowed_addrs(unit, addrs, opts);
1962 else if (opts != 0)
1963 free_wordlist(opts);
1964 if (addrs != 0)
1965 free_wordlist(addrs);
1966 }
1967
1968 len = strlen(secbuf);
1969 if (len > MAXSECRETLEN) {
1970 ppp_error(("Secret for %s on %s is too long", client, server));
1971 len = MAXSECRETLEN;
1972 }
1973 MEMCPY(secret, secbuf, len);
1974 BZERO(secbuf, sizeof(secbuf));
1975 *secret_len = len;
1976
1977 return 1;
1978#endif /* UNUSED */
1979}
1980#endif /* PPP_AUTH_SUPPORT */
1981
1982
1983#if 0 /* UNUSED */
1984/*
1985 * get_srp_secret - open the SRP secret file and return the secret
1986 * for authenticating the given client on the given server.
1987 * (We could be either client or server).
1988 */
1989int
1990get_srp_secret(unit, client, server, secret, am_server)
1991 int unit;
1992 char *client;
1993 char *server;
1994 char *secret;
1995 int am_server;
1996{
1997 FILE *fp;
1998 int ret;
1999 char *filename;
2000 struct wordlist *addrs, *opts;
2001
2002 if (!am_server && ppp_settings.passwd[0] != '\0') {
2003 strlcpy(secret, ppp_settings.passwd, MAXWORDLEN);
2004 } else {
2005 filename = _PATH_SRPFILE;
2006 addrs = NULL;
2007
2008 fp = fopen(filename, "r");
2009 if (fp == NULL) {
2010 ppp_error(("Can't open srp secret file %s: %m", filename));
2011 return 0;
2012 }
2014
2015 secret[0] = '\0';
2016 ret = scan_authfile(fp, client, server, secret, &addrs, &opts,
2017 filename, am_server);
2018 fclose(fp);
2019 if (ret < 0)
2020 return 0;
2021
2022 if (am_server)
2023 set_allowed_addrs(unit, addrs, opts);
2024 else if (opts != NULL)
2025 free_wordlist(opts);
2026 if (addrs != NULL)
2027 free_wordlist(addrs);
2028 }
2029
2030 return 1;
2031}
2032
2033/*
2034 * set_allowed_addrs() - set the list of allowed addresses.
2035 * Also looks for `--' indicating options to apply for this peer
2036 * and leaves the following words in extra_options.
2037 */
2038static void
2039set_allowed_addrs(unit, addrs, opts)
2040 int unit;
2041 struct wordlist *addrs;
2042 struct wordlist *opts;
2043{
2044 int n;
2045 struct wordlist *ap, **plink;
2046 struct permitted_ip *ip;
2047 char *ptr_word, *ptr_mask;
2048 struct hostent *hp;
2049 struct netent *np;
2050 u32_t a, mask, ah, offset;
2051 struct ipcp_options *wo = &ipcp_wantoptions[unit];
2052 u32_t suggested_ip = 0;
2053
2054 if (addresses[unit] != NULL)
2055 free(addresses[unit]);
2056 addresses[unit] = NULL;
2057 if (extra_options != NULL)
2058 free_wordlist(extra_options);
2059 extra_options = opts;
2060
2061 /*
2062 * Count the number of IP addresses given.
2063 */
2064 n = wordlist_count(addrs) + wordlist_count(noauth_addrs);
2065 if (n == 0)
2066 return;
2067 ip = (struct permitted_ip *) malloc((n + 1) * sizeof(struct permitted_ip));
2068 if (ip == 0)
2069 return;
2070
2071 /* temporarily append the noauth_addrs list to addrs */
2072 for (plink = &addrs; *plink != NULL; plink = &(*plink)->next)
2073 ;
2074 *plink = noauth_addrs;
2075
2076 n = 0;
2077 for (ap = addrs; ap != NULL; ap = ap->next) {
2078 /* "-" means no addresses authorized, "*" means any address allowed */
2079 ptr_word = ap->word;
2080 if (strcmp(ptr_word, "-") == 0)
2081 break;
2082 if (strcmp(ptr_word, "*") == 0) {
2083 ip[n].permit = 1;
2084 ip[n].base = ip[n].mask = 0;
2085 ++n;
2086 break;
2087 }
2088
2089 ip[n].permit = 1;
2090 if (*ptr_word == '!') {
2091 ip[n].permit = 0;
2092 ++ptr_word;
2093 }
2094
2095 mask = ~ (u32_t) 0;
2096 offset = 0;
2097 ptr_mask = strchr (ptr_word, '/');
2098 if (ptr_mask != NULL) {
2099 int bit_count;
2100 char *endp;
2101
2102 bit_count = (int) strtol (ptr_mask+1, &endp, 10);
2103 if (bit_count <= 0 || bit_count > 32) {
2104 ppp_warn(("invalid address length %v in auth. address list",
2105 ptr_mask+1));
2106 continue;
2107 }
2108 bit_count = 32 - bit_count; /* # bits in host part */
2109 if (*endp == '+') {
2110 offset = ifunit + 1;
2111 ++endp;
2112 }
2113 if (*endp != 0) {
2114 ppp_warn(("invalid address length syntax: %v", ptr_mask+1));
2115 continue;
2116 }
2117 *ptr_mask = '\0';
2118 mask <<= bit_count;
2119 }
2120
2121 hp = gethostbyname(ptr_word);
2122 if (hp != NULL && hp->h_addrtype == AF_INET) {
2123 a = *(u32_t *)hp->h_addr;
2124 } else {
2125 np = getnetbyname (ptr_word);
2126 if (np != NULL && np->n_addrtype == AF_INET) {
2127 a = lwip_htonl ((u32_t)np->n_net);
2128 if (ptr_mask == NULL) {
2129 /* calculate appropriate mask for net */
2130 ah = lwip_ntohl(a);
2131 if (IN_CLASSA(ah))
2133 else if (IN_CLASSB(ah))
2135 else if (IN_CLASSC(ah))
2137 }
2138 } else {
2139 a = inet_addr (ptr_word);
2140 }
2141 }
2142
2143 if (ptr_mask != NULL)
2144 *ptr_mask = '/';
2145
2146 if (a == (u32_t)-1L) {
2147 ppp_warn(("unknown host %s in auth. address list", ap->word));
2148 continue;
2149 }
2150 if (offset != 0) {
2151 if (offset >= ~mask) {
2152 ppp_warn(("interface unit %d too large for subnet %v",
2153 ifunit, ptr_word));
2154 continue;
2155 }
2156 a = lwip_htonl((lwip_ntohl(a) & mask) + offset);
2157 mask = ~(u32_t)0;
2158 }
2159 ip[n].mask = lwip_htonl(mask);
2160 ip[n].base = a & ip[n].mask;
2161 ++n;
2162 if (~mask == 0 && suggested_ip == 0)
2163 suggested_ip = a;
2164 }
2165 *plink = NULL;
2166
2167 ip[n].permit = 0; /* make the last entry forbid all addresses */
2168 ip[n].base = 0; /* to terminate the list */
2169 ip[n].mask = 0;
2170
2171 addresses[unit] = ip;
2172
2173 /*
2174 * If the address given for the peer isn't authorized, or if
2175 * the user hasn't given one, AND there is an authorized address
2176 * which is a single host, then use that if we find one.
2177 */
2178 if (suggested_ip != 0
2179 && (wo->hisaddr == 0 || !auth_ip_addr(unit, wo->hisaddr))) {
2180 wo->hisaddr = suggested_ip;
2181 /*
2182 * Do we insist on this address? No, if there are other
2183 * addresses authorized than the suggested one.
2184 */
2185 if (n > 1)
2186 wo->accept_remote = 1;
2187 }
2188}
2189
2190/*
2191 * auth_ip_addr - check whether the peer is authorized to use
2192 * a given IP address. Returns 1 if authorized, 0 otherwise.
2193 */
2194int
2195auth_ip_addr(unit, addr)
2196 int unit;
2197 u32_t addr;
2198{
2199 int ok;
2200
2201 /* don't allow loopback or multicast address */
2202 if (bad_ip_adrs(addr))
2203 return 0;
2204
2205 if (allowed_address_hook) {
2206 ok = allowed_address_hook(addr);
2207 if (ok >= 0) return ok;
2208 }
2209
2210 if (addresses[unit] != NULL) {
2211 ok = ip_addr_check(addr, addresses[unit]);
2212 if (ok >= 0)
2213 return ok;
2214 }
2215
2216 if (auth_required)
2217 return 0; /* no addresses authorized */
2218 return allow_any_ip || privileged || !have_route_to(addr);
2219}
2220
2221static int
2222ip_addr_check(addr, addrs)
2223 u32_t addr;
2224 struct permitted_ip *addrs;
2225{
2226 for (; ; ++addrs)
2227 if ((addr & addrs->mask) == addrs->base)
2228 return addrs->permit;
2229}
2230
2231/*
2232 * bad_ip_adrs - return 1 if the IP address is one we don't want
2233 * to use, such as an address in the loopback net or a multicast address.
2234 * addr is in network byte order.
2235 */
2236int
2237bad_ip_adrs(addr)
2238 u32_t addr;
2239{
2240 addr = lwip_ntohl(addr);
2241 return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
2243}
2244
2245/*
2246 * some_ip_ok - check a wordlist to see if it authorizes any
2247 * IP address(es).
2248 */
2249static int
2250some_ip_ok(addrs)
2251 struct wordlist *addrs;
2252{
2253 for (; addrs != 0; addrs = addrs->next) {
2254 if (addrs->word[0] == '-')
2255 break;
2256 if (addrs->word[0] != '!')
2257 return 1; /* some IP address is allowed */
2258 }
2259 return 0;
2260}
2261
2262/*
2263 * auth_number - check whether the remote number is allowed to connect.
2264 * Returns 1 if authorized, 0 otherwise.
2265 */
2266int
2267auth_number()
2268{
2269 struct wordlist *wp = permitted_numbers;
2270 int l;
2271
2272 /* Allow all if no authorization list. */
2273 if (!wp)
2274 return 1;
2275
2276 /* Allow if we have a match in the authorization list. */
2277 while (wp) {
2278 /* trailing '*' wildcard */
2279 l = strlen(wp->word);
2280 if ((wp->word)[l - 1] == '*')
2281 l--;
2282 if (!strncasecmp(wp->word, remote_number, l))
2283 return 1;
2284 wp = wp->next;
2285 }
2286
2287 return 0;
2288}
2289
2290/*
2291 * check_access - complain if a secret file has too-liberal permissions.
2292 */
2293static void
2295 FILE *f;
2296 char *filename;
2297{
2298 struct stat sbuf;
2299
2300 if (fstat(fileno(f), &sbuf) < 0) {
2301 ppp_warn(("cannot stat secret file %s: %m", filename));
2302 } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
2303 ppp_warn(("Warning - secret file %s has world and/or group access",
2304 filename));
2305 }
2306}
2307
2308/*
2309 * scan_authfile - Scan an authorization file for a secret suitable
2310 * for authenticating `client' on `server'. The return value is -1
2311 * if no secret is found, otherwise >= 0. The return value has
2312 * NONWILD_CLIENT set if the secret didn't have "*" for the client, and
2313 * NONWILD_SERVER set if the secret didn't have "*" for the server.
2314 * Any following words on the line up to a "--" (i.e. address authorization
2315 * info) are placed in a wordlist and returned in *addrs. Any
2316 * following words (extra options) are placed in a wordlist and
2317 * returned in *opts.
2318 * We assume secret is NULL or points to MAXWORDLEN bytes of space.
2319 * Flags are non-zero if we need two colons in the secret in order to
2320 * match.
2321 */
2322static int
2323scan_authfile(f, client, server, secret, addrs, opts, filename, flags)
2324 FILE *f;
2325 char *client;
2326 char *server;
2327 char *secret;
2328 struct wordlist **addrs;
2329 struct wordlist **opts;
2330 char *filename;
2331 int flags;
2332{
2333 int newline, xxx;
2334 int got_flag, best_flag;
2335 FILE *sf;
2336 struct wordlist *ap, *addr_list, *alist, **app;
2337 char word[MAXWORDLEN];
2338 char atfile[MAXWORDLEN];
2339 char lsecret[MAXWORDLEN];
2340 char *cp;
2341
2342 if (addrs != NULL)
2343 *addrs = NULL;
2344 if (opts != NULL)
2345 *opts = NULL;
2346 addr_list = NULL;
2347 if (!getword(f, word, &newline, filename))
2348 return -1; /* file is empty??? */
2349 newline = 1;
2350 best_flag = -1;
2351 for (;;) {
2352 /*
2353 * Skip until we find a word at the start of a line.
2354 */
2355 while (!newline && getword(f, word, &newline, filename))
2356 ;
2357 if (!newline)
2358 break; /* got to end of file */
2359
2360 /*
2361 * Got a client - check if it's a match or a wildcard.
2362 */
2363 got_flag = 0;
2364 if (client != NULL && strcmp(word, client) != 0 && !ISWILD(word)) {
2365 newline = 0;
2366 continue;
2367 }
2368 if (!ISWILD(word))
2369 got_flag = NONWILD_CLIENT;
2370
2371 /*
2372 * Now get a server and check if it matches.
2373 */
2374 if (!getword(f, word, &newline, filename))
2375 break;
2376 if (newline)
2377 continue;
2378 if (!ISWILD(word)) {
2379 if (server != NULL && strcmp(word, server) != 0)
2380 continue;
2381 got_flag |= NONWILD_SERVER;
2382 }
2383
2384 /*
2385 * Got some sort of a match - see if it's better than what
2386 * we have already.
2387 */
2388 if (got_flag <= best_flag)
2389 continue;
2390
2391 /*
2392 * Get the secret.
2393 */
2394 if (!getword(f, word, &newline, filename))
2395 break;
2396 if (newline)
2397 continue;
2398
2399 /*
2400 * SRP-SHA1 authenticator should never be reading secrets from
2401 * a file. (Authenticatee may, though.)
2402 */
2403 if (flags && ((cp = strchr(word, ':')) == NULL ||
2404 strchr(cp + 1, ':') == NULL))
2405 continue;
2406
2407 if (secret != NULL) {
2408 /*
2409 * Special syntax: @/pathname means read secret from file.
2410 */
2411 if (word[0] == '@' && word[1] == '/') {
2412 strlcpy(atfile, word+1, sizeof(atfile));
2413 if ((sf = fopen(atfile, "r")) == NULL) {
2414 ppp_warn(("can't open indirect secret file %s", atfile));
2415 continue;
2416 }
2417 check_access(sf, atfile);
2418 if (!getword(sf, word, &xxx, atfile)) {
2419 ppp_warn(("no secret in indirect secret file %s", atfile));
2420 fclose(sf);
2421 continue;
2422 }
2423 fclose(sf);
2424 }
2425 strlcpy(lsecret, word, sizeof(lsecret));
2426 }
2427
2428 /*
2429 * Now read address authorization info and make a wordlist.
2430 */
2431 app = &alist;
2432 for (;;) {
2433 if (!getword(f, word, &newline, filename) || newline)
2434 break;
2435 ap = (struct wordlist *)
2436 malloc(sizeof(struct wordlist) + strlen(word) + 1);
2437 if (ap == NULL)
2438 novm("authorized addresses");
2439 ap->word = (char *) (ap + 1);
2440 strcpy(ap->word, word);
2441 *app = ap;
2442 app = &ap->next;
2443 }
2444 *app = NULL;
2445
2446 /*
2447 * This is the best so far; remember it.
2448 */
2449 best_flag = got_flag;
2450 if (addr_list)
2451 free_wordlist(addr_list);
2452 addr_list = alist;
2453 if (secret != NULL)
2454 strlcpy(secret, lsecret, MAXWORDLEN);
2455
2456 if (!newline)
2457 break;
2458 }
2459
2460 /* scan for a -- word indicating the start of options */
2461 for (app = &addr_list; (ap = *app) != NULL; app = &ap->next)
2462 if (strcmp(ap->word, "--") == 0)
2463 break;
2464 /* ap = start of options */
2465 if (ap != NULL) {
2466 ap = ap->next; /* first option */
2467 free(*app); /* free the "--" word */
2468 *app = NULL; /* terminate addr list */
2469 }
2470 if (opts != NULL)
2471 *opts = ap;
2472 else if (ap != NULL)
2473 free_wordlist(ap);
2474 if (addrs != NULL)
2475 *addrs = addr_list;
2476 else if (addr_list != NULL)
2477 free_wordlist(addr_list);
2478
2479 return best_flag;
2480}
2481
2482/*
2483 * wordlist_count - return the number of items in a wordlist
2484 */
2485static int
2486wordlist_count(wp)
2487 struct wordlist *wp;
2488{
2489 int n;
2490
2491 for (n = 0; wp != NULL; wp = wp->next)
2492 ++n;
2493 return n;
2494}
2495
2496/*
2497 * free_wordlist - release memory allocated for a wordlist.
2498 */
2499static void
2500free_wordlist(wp)
2501 struct wordlist *wp;
2502{
2503 struct wordlist *next;
2504
2505 while (wp != NULL) {
2506 next = wp->next;
2507 free(wp);
2508 wp = next;
2509 }
2510}
2511#endif /* UNUSED */
2512
2513#endif /* PPP_SUPPORT */
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define fileno
Definition: acwin.h:102
#define fstat
Definition: acwin.h:100
ULONG WSAAPI inet_addr(IN CONST CHAR FAR *cp)
Definition: addrconv.c:71
static int used
Definition: adh-main.c:39
#define ok(value,...)
Definition: atltest.h:57
#define msg(x)
Definition: auth_time.c:54
long uid_t
Definition: various.h:8
void idle(int argc, const char *argv[])
Definition: cmds.c:1581
void user(int argc, const char *argv[])
Definition: cmds.c:1350
void disconnect(int argc, const char *argv[])
Definition: cmds.c:1620
char * hostname
Definition: ftp.c:88
uid_t getuid()
Definition: uid.c:27
size_t strlcpy(char *d, const char *s, size_t bufsize)
Definition: compat.c:3
struct protocol * protocols
Definition: dispatch.c:56
r l[0]
Definition: byte_order.h:168
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define lwip_ntohl(x)
Definition: def.h:89
#define LWIP_MIN(x, y)
Definition: def.h:66
#define lwip_htonl(x)
Definition: def.h:88
UINT32 u_int
Definition: types.h:82
#define NULL
Definition: types.h:112
struct netent *WINAPI getnetbyname(const char *name)
Definition: stubs.c:254
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
__kernel_time_t time_t
Definition: linux.h:252
#define AF_INET
Definition: tcpip.h:117
#define S_IRWXG
Definition: ext2fs.h:388
#define S_IRWXO
Definition: ext2fs.h:394
#define strncasecmp
Definition: fake.h:10
PHOSTENT WSAAPI gethostbyname(IN const char FAR *name)
Definition: getxbyxx.c:221
GLdouble n
Definition: glext.h:7729
GLsizei GLuint * groups
Definition: glext.h:11113
GLintptr offset
Definition: glext.h:5920
GLint namelen
Definition: glext.h:7232
GLenum GLint GLuint mask
Definition: glext.h:6028
GLfloat f
Definition: glext.h:7540
GLbitfield flags
Definition: glext.h:7161
GLboolean GLuint group
Definition: glext.h:11120
GLenum const GLvoid * addr
Definition: glext.h:9621
GLboolean GLboolean g
Definition: glext.h:6204
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
uint32_t u32_t
Definition: arch.h:129
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:373
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
_Check_return_opt_ _CRTIMP char *__cdecl fgets(_Out_writes_z_(_MaxCount) char *_Buf, _In_ int _MaxCount, _Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fclose(_Inout_ FILE *_File)
_Check_return_ long __cdecl strtol(_In_z_ const char *_Str, _Out_opt_ _Deref_post_z_ char **_EndPtr, _In_ int _Radix)
const char * filename
Definition: ioapi.h:137
const WCHAR * word
Definition: lex.c:36
#define f
Definition: ke_i.h:83
#define a
Definition: ke_i.h:78
#define sleep
Definition: syshdrs.h:37
if(dx< 0)
Definition: linetemp.h:194
#define IN_CLASSA(a)
Definition: inet.h:97
#define IN_LOOPBACKNET
Definition: inet.h:126
#define IN_CLASSB(b)
Definition: inet.h:103
#define IN_CLASSA_NET
Definition: inet.h:98
#define IN_CLASSA_NSHIFT
Definition: inet.h:99
#define IN_CLASSC_NET
Definition: inet.h:110
#define IN_MULTICAST(a)
Definition: inet.h:121
#define IN_BADCLASS(a)
Definition: inet.h:124
#define IN_CLASSC(c)
Definition: inet.h:109
#define IN_CLASSB_NET
Definition: inet.h:104
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
POINT cp
Definition: magnifier.c:59
#define MAXNAMELEN
Definition: maxpath.h:119
static DATA_BLOB CRYPTPROTECT_PROMPTSTRUCT DATA_BLOB *static LPWSTR DATA_BLOB CRYPTPROTECT_PROMPTSTRUCT DATA_BLOB *static char secret[]
Definition: protectdata.c:33
static unsigned int number
Definition: dsound.c:1479
static void check_access(LPCWSTR filename, const struct lock_test *current, DWORD access, DWORD sharing, const char *desc, DWORD open_mode, BOOL *any_failure)
Definition: storage32.c:3465
#define argv
Definition: mplay32.c:18
int notify
Definition: msacm.c:1366
#define TIMEOUT
Definition: ntpclient.c:12
png_const_structrp png_const_inforp int * unit
Definition: png.h:2159
static unsigned __int64 next
Definition: rand_nt.c:6
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
strcpy
Definition: string.h:131
#define exit(n)
Definition: config.h:202
static FILE * client
Definition: client.c:41
struct define * next
Definition: compiler.c:65
short h_addrtype
Definition: winsock.h:136
Definition: dhcpd.h:62
Definition: name.c:39
u_long n_net
Definition: winsock.h:155
short n_addrtype
Definition: winsock.h:154
Definition: stat.h:55
Definition: ps.c:97
EXPORT uid_t geteuid()
Definition: uid.c:37
EXPORT int seteuid(uid_t uid)
Definition: uid.c:58
static rfbScreenInfoPtr server
Definition: vnc.c:74
int ret
void * arg
Definition: msvc.h:10
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
void fatal(const char *msg)