auth.c
上传用户:nvosite88
上传日期:2007-01-17
资源大小:4983k
文件大小:23k
源码类别:

VxWorks

开发平台:

C/C++

  1. /* auth.c - PPP authentication and phase control */
  2. /* Copyright 1995 Wind River Systems, Inc. */
  3. #include "copyright_wrs.h"
  4. /*
  5.  * Copyright (c) 1993 The Australian National University.
  6.  * All rights reserved.
  7.  *
  8.  * Redistribution and use in source and binary forms are permitted
  9.  * provided that the above copyright notice and this paragraph are
  10.  * duplicated in all such forms and that any documentation,
  11.  * advertising materials, and other materials related to such
  12.  * distribution and use acknowledge that the software was developed
  13.  * by the Australian National University.  The name of the University
  14.  * may not be used to endorse or promote products derived from this
  15.  * software without specific prior written permission.
  16.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  17.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  18.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  19.  *
  20.  * Copyright (c) 1989 Carnegie Mellon University.
  21.  * All rights reserved.
  22.  *
  23.  * Redistribution and use in source and binary forms are permitted
  24.  * provided that the above copyright notice and this paragraph are
  25.  * duplicated in all such forms and that any documentation,
  26.  * advertising materials, and other materials related to such
  27.  * distribution and use acknowledge that the software was developed
  28.  * by Carnegie Mellon University.  The name of the
  29.  * University may not be used to endorse or promote products derived
  30.  * from this software without specific prior written permission.
  31.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  32.  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  33.  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  34.  */
  35. /*
  36. modification history
  37. --------------------
  38. 01l,14feb97,ms   allow VxSim/Solaris to use 127.x.x.x addresses
  39. 01k,30jul95,dzb  fixed to avoid trying to open NULL filenames (SPR #4560).
  40. 01j,26jun95,dzb  removed usehostname option.
  41. 01i,21jun95,dzb  created pppCryptRtn to unbundled DES encryption.
  42. 01h,16jun95,dzb  header file consolidation.
  43. 01g,07jun95,dzb  make sure we got neg_chap when we "required" CHAP.
  44.                  made LOG_NOTICE message printed even w/o debug option.
  45. 01f,11may95,dzb  added calls to pppSecretLib for VxWorks secrets table.
  46.                  added call to loginUserVerify() for "login" option.
  47.  re-activated auth_ip_addr() checking.
  48.  switched lcp_close() calls to go through die().
  49.  moved WILD defines to auth.h.  removed logged_in and logout().
  50.  removed checking for attempts at password checking.
  51. 01e,05may95,dzb  check for null client/server strings in scan_authfile().
  52. 01d,13feb95,dab  added check for debug option in link_terminated().
  53. 01c,09feb95,dab  removed the UNIX-centric routine login().
  54. 01b,16jan95,dab  reverse params for crypt() call.
  55. 01a,21dec94,dab  VxWorks port - first WRS version.
  56.            +dzb  added: path for ppp header files, WRS copyright.
  57. */
  58. #include "vxWorks.h"
  59. #include "stdio.h"
  60. #include "string.h"
  61. #include "sysLib.h"
  62. #include "taskLib.h"
  63. #include "loginLib.h"
  64. #include "hostLib.h"
  65. #include "sys/types.h"
  66. #include "sys/stat.h"
  67. #include "netinet/in.h"
  68. #include "arpa/inet.h"
  69. #include "pppLib.h"
  70. /* Bits in auth_pending[] */
  71. #define UPAP_WITHPEER 1
  72. #define UPAP_PEER 2
  73. #define CHAP_WITHPEER 4
  74. #define CHAP_PEER 8
  75. /* Prototypes */
  76. static int  null_login __ARGS((int));
  77. static int  get_upap_passwd __ARGS((void));
  78. static int  have_upap_secret __ARGS((void));
  79. static int  have_chap_secret __ARGS((char *, char *));
  80. static int  scan_authfile __ARGS((FILE *, char *, char *, char *,
  81.   struct wordlist **, char *));
  82. static void free_wordlist __ARGS((struct wordlist *));
  83. FUNCPTR pppCryptRtn = NULL; /* PPP cryptographic authentication routine */
  84. /*
  85.  * An Open on LCP has requested a change from Dead to Establish phase.
  86.  * Do what's necessary to bring the physical layer up.
  87.  */
  88. void
  89. link_required(unit)
  90. int unit;
  91. {
  92. }
  93. /*
  94.  * LCP has terminated the link; go to the Dead phase and take the
  95.  * physical layer down.
  96.  */
  97. void
  98. link_terminated(unit)
  99. int unit;
  100. {
  101.     ppp_if[unit]->phase = PHASE_DEAD;
  102.     syslog(LOG_NOTICE, "Connection terminated.");
  103. }
  104. /*
  105.  * LCP has gone down; it will either die or try to re-establish.
  106.  */
  107. void
  108. link_down(unit)
  109.     int unit;
  110. {
  111.     ppp_if[unit]->phase = PHASE_TERMINATE;
  112. }
  113. /*
  114.  * The link is established.
  115.  * Proceed to the Dead, Authenticate or Network phase as appropriate.
  116.  */
  117. void
  118. link_established(unit)
  119. int unit;
  120. {
  121.     int auth;
  122.     lcp_options *wo = &ppp_if[unit]->lcp_wantoptions;
  123.     lcp_options *go = &ppp_if[unit]->lcp_gotoptions;
  124.     lcp_options *ho = &ppp_if[unit]->lcp_hisoptions;
  125.     if (ppp_if[unit]->auth_required && !(go->neg_chap || go->neg_upap)) {
  126. /*
  127.          * We wanted the peer to authenticate itself, and it refused:
  128.          * treat it as though it authenticated with PAP using a username
  129.          * of "" and a password of "".  If that's not OK, boot it out.
  130.  *
  131.  * NB:
  132.  * Changed this "if" statement to look for requiring CHAP and
  133.  * not PAP (covered by !wo->neg_upap), so that peer cannot simply
  134.  * refuse CHAP and get away with it...
  135.  */
  136.         if (!wo->neg_upap || !null_login(unit)) {
  137.             syslog(LOG_WARNING, "peer refused to authenticate");
  138.     die(unit, 1);
  139.         }
  140.     }
  141.     ppp_if[unit]->phase = PHASE_AUTHENTICATE;
  142.     auth = 0;
  143.     if (go->neg_chap) {
  144. ChapAuthPeer(unit, ppp_if[unit]->our_name, go->chap_mdtype);
  145. auth |= CHAP_PEER;
  146.     } else if (go->neg_upap) {
  147. upap_authpeer(unit);
  148. auth |= UPAP_PEER;
  149.     }
  150.     if (ho->neg_chap) {
  151. ChapAuthWithPeer(unit, ppp_if[unit]->our_name, ho->chap_mdtype);
  152. auth |= CHAP_WITHPEER;
  153.     } else if (ho->neg_upap) {
  154. upap_authwithpeer(unit, ppp_if[unit]->user, ppp_if[unit]->passwd);
  155. auth |= UPAP_WITHPEER;
  156.     }
  157.     ppp_if[unit]->auth_pending = auth;
  158.     if (!auth) {
  159.         ppp_if[unit]->phase = PHASE_NETWORK;
  160.         ipcp_open(unit);
  161.     }
  162. }
  163. /*
  164.  * The peer has failed to authenticate himself using `protocol'.
  165.  */
  166. void
  167. auth_peer_fail(unit, protocol)
  168.     int unit, protocol;
  169. {
  170.     /*
  171.      * Authentication failure: take the link down
  172.      */
  173.     die(unit, 1);
  174. }
  175. /*
  176.  * The peer has been successfully authenticated using `protocol'.
  177.  */
  178. void
  179. auth_peer_success(unit, protocol)
  180.     int unit, protocol;
  181. {
  182.     int bit;
  183.     switch (protocol) {
  184.     case CHAP:
  185. bit = CHAP_PEER;
  186. break;
  187.     case UPAP:
  188. bit = UPAP_PEER;
  189. break;
  190.     default:
  191. syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
  192.                protocol);
  193. return;
  194.     }
  195.     /*
  196.      * If there is no more authentication still to be done,
  197.      * proceed to the network phase.
  198.      */
  199.     if ((ppp_if[unit]->auth_pending &= ~bit) == 0) {
  200.         ppp_if[unit]->phase = PHASE_NETWORK;
  201. ipcp_open(unit);
  202.     }
  203. }
  204. /*
  205.  * We have failed to authenticate ourselves to the peer using `protocol'.
  206.  */
  207. void
  208. auth_withpeer_fail(unit, protocol)
  209.     int unit, protocol;
  210. {
  211.     /*
  212.      * We've failed to authenticate ourselves to our peer.
  213.      * He'll probably take the link down, and there's not much
  214.      * we can do except wait for that.
  215.      */
  216. }
  217. /*
  218.  * We have successfully authenticated ourselves with the peer using `protocol'.
  219.  */
  220. void
  221. auth_withpeer_success(unit, protocol)
  222.     int unit, protocol;
  223. {
  224.     int bit;
  225.     switch (protocol) {
  226.     case CHAP:
  227. bit = CHAP_WITHPEER;
  228. break;
  229.     case UPAP:
  230. bit = UPAP_WITHPEER;
  231. break;
  232.     default:
  233. syslog(LOG_WARNING, "auth_peer_success: unknown protocol %x",
  234.                protocol);
  235.         bit = 0;
  236.     }
  237.     /*
  238.      * If there is no more authentication still being done,
  239.      * proceed to the network phase.
  240.      */
  241.     if ((ppp_if[unit]->auth_pending &= ~bit) == 0) {
  242.         ppp_if[unit]->phase = PHASE_NETWORK;
  243. ipcp_open(unit);
  244.     }
  245. }
  246. /*
  247.  * check_auth_options - called to check authentication options.
  248.  */
  249. void
  250. check_auth_options()
  251. {
  252.     lcp_options *wo = &ppp_if[ppp_unit]->lcp_wantoptions;
  253.     lcp_options *ao = &ppp_if[ppp_unit]->lcp_allowoptions;
  254.     /* Default our_name to hostname, and user to our_name */
  255.     if (ppp_if[ppp_unit]->our_name[0] == 0)
  256. strcpy(ppp_if[ppp_unit]->our_name, ppp_if[ppp_unit]->hostname);
  257.     if (ppp_if[ppp_unit]->user[0] == 0)
  258. strcpy(ppp_if[ppp_unit]->user, ppp_if[ppp_unit]->our_name);
  259.     /* If authentication is required, ask peer for CHAP or PAP. */
  260.     if (ppp_if[ppp_unit]->auth_required && !wo->neg_chap && !wo->neg_upap) {
  261. wo->neg_chap = 1;
  262. wo->neg_upap = 1;
  263.     }
  264.     /*
  265.      * Check whether we have appropriate secrets to use
  266.      * to authenticate ourselves and/or the peer.
  267.      */
  268.     if (ao->neg_upap && ppp_if[ppp_unit]->passwd[0] == 0 && !get_upap_passwd())
  269. ao->neg_upap = 0;
  270.     if (wo->neg_upap && !ppp_if[ppp_unit]->uselogin && !have_upap_secret())
  271. wo->neg_upap = 0;
  272.     if (ao->neg_chap && !have_chap_secret(ppp_if[ppp_unit]->our_name, ppp_if[ppp_unit]->remote_name))
  273. ao->neg_chap = 0;
  274.     if (wo->neg_chap && !have_chap_secret(ppp_if[ppp_unit]->remote_name, ppp_if[ppp_unit]->our_name))
  275. wo->neg_chap = 0;
  276.     if (ppp_if[ppp_unit]->auth_required && !wo->neg_chap && !wo->neg_upap) {
  277. syslog(LOG_ERR, "peer authentication required but no authentication files accessible");
  278. die(ppp_unit, 1);
  279.     }
  280. }
  281. /*
  282.  * check_passwd - Check the user name and passwd against the PAP secrets
  283.  * file.  If requested, also check against the system password database,
  284.  * and login the user if OK.
  285.  *
  286.  * returns:
  287.  * UPAP_AUTHNAK: Authentication failed.
  288.  * UPAP_AUTHACK: Authentication succeeded.
  289.  * In either case, msg points to an appropriate message.
  290.  */
  291. int
  292. check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen)
  293.     int unit;
  294.     char *auser;
  295.     int userlen;
  296.     char *apasswd;
  297.     int passwdlen;
  298.     char **msg;
  299.     int *msglen;
  300. {
  301.     int ret = UPAP_AUTHACK;
  302.     char *filename;
  303.     FILE *f = NULL;
  304.     struct wordlist *addrs = NULL;
  305.     char passwd[256], user[256];
  306.     char secret[MAXWORDLEN];
  307.     /*
  308.      * Make copies of apasswd and auser, then null-terminate them.
  309.      */
  310.     BCOPY(apasswd, passwd, passwdlen);
  311.     passwd[passwdlen] = '';
  312.     BCOPY(auser, user, userlen);
  313.     user[userlen] = '';
  314.     if (ppp_if[unit]->uselogin)
  315. {
  316.         if (loginUserVerify (user, passwd) == ERROR)
  317.     {
  318.     ret = UPAP_AUTHNAK;
  319.             syslog(LOG_WARNING, "upap login failure for %s", user);
  320.     }
  321.         }
  322.     else if (pppSecretFind (user, ppp_if[unit]->our_name, secret, &addrs) < 0 ||
  323.         (secret[0] != 0 && strcmp(passwd, secret) != 0 &&
  324. ((pppCryptRtn == NULL) ||
  325.         strcmp((char *) (*pppCryptRtn) (secret, passwd), passwd) != 0)))
  326.         {
  327.         /*
  328.          * Open the file of upap secrets and scan for a suitable secret
  329.          * for authenticating this user.
  330.          */
  331.         if ((filename = ppp_if[unit]->options->pap_file) != NULL)
  332.             f = fopen(filename, "r");
  333.         if (f == NULL) {
  334.     syslog(LOG_ERR, "Can't open upap password file %s", filename);
  335.     ret = UPAP_AUTHNAK;
  336.         } else {
  337.     check_access(f, filename);
  338.             if (scan_authfile(f, user, ppp_if[unit]->our_name, secret,
  339. &addrs, filename) < 0 || (secret[0] != 0 &&
  340. strcmp(passwd, secret) != 0 && ((pppCryptRtn == NULL) ||
  341. strcmp((char *) (*pppCryptRtn) (secret, passwd), passwd) != 0)))
  342. {
  343.                 syslog(LOG_WARNING, "upap authentication failure for %s", user);
  344.         ret = UPAP_AUTHNAK;
  345.         }
  346.     fclose(f);
  347.             }
  348.         }
  349.     if (ret == UPAP_AUTHNAK) {
  350.         *msg = "Login incorrect";
  351.         *msglen = strlen(*msg);
  352. if (addrs != NULL)
  353.     free_wordlist(addrs);
  354.     } else {
  355. *msg = "Login ok";
  356. *msglen = strlen(*msg);
  357. if (ppp_if[unit]->addresses != NULL)
  358.     free_wordlist(ppp_if[unit]->addresses);
  359. ppp_if[unit]->addresses = addrs;
  360.     }
  361.     return ret;
  362. }
  363. /*
  364.  * upap_login - Check the user name and password against the system
  365.  * password database, and login the user if OK.
  366.  *
  367.  * returns:
  368.  * UPAP_AUTHNAK: Login failed.
  369.  * UPAP_AUTHACK: Login succeeded.
  370.  * In either case, msg points to an appropriate message.
  371.  */
  372. #ifdef notyet
  373. static int
  374. login(user, passwd)
  375.     char *user;
  376.     char *passwd;
  377. {
  378.     struct passwd *pw;
  379.     char *epasswd;
  380.     char *tty;
  381.     if ((pw = getpwnam(user)) == NULL) {
  382.         return (UPAP_AUTHNAK);
  383.     }
  384.     /*
  385.      * XXX If no passwd, let them login without one.
  386.      */
  387.     if (pw->pw_passwd == '') {
  388.         return (UPAP_AUTHACK);
  389.     }
  390.     epasswd = crypt(passwd, pw->pw_passwd);
  391.     if (strcmp(epasswd, pw->pw_passwd)) {
  392.         return (UPAP_AUTHNAK);
  393.     }
  394.     syslog(LOG_INFO, "user %s logged in", user);
  395.     /*
  396.      * Write a wtmp entry for this user.
  397.      */
  398.     tty = strrchr(devname, '/');
  399.     if (tty == NULL)
  400.         tty = devname;
  401.     else
  402.         tty++;
  403.     logwtmp(tty, user, "");             /* Add wtmp login entry */
  404.     logged_in = TRUE;
  405. }
  406. /*
  407.  * logout - Logout the user.
  408.  */
  409. static void
  410. logout()
  411. {
  412.     char *tty;
  413.     tty = strrchr(ppp_if[ppp_unit]->devname, '/');
  414.     if (tty == NULL)
  415. tty = ppp_if[ppp_unit]->devname;
  416.     else
  417. tty++;
  418.     ppp_if[ppp_unit]->logged_in = FALSE;
  419. }
  420. #endif /* notyet */
  421. /*
  422.  * null_login - Check if a username of "" and a password of "" are
  423.  * acceptable, and iff so, set the list of acceptable IP addresses
  424.  * and return 1.
  425.  */
  426. static int
  427. null_login(unit)
  428.     int unit;
  429. {
  430.     char *filename;
  431.     FILE *f = NULL;
  432.     int i, ret;
  433.     struct wordlist *addrs = NULL;
  434.     char secret[MAXWORDLEN];
  435.     i = pppSecretFind ("", ppp_if[unit]->our_name, secret, &addrs);
  436.     ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0;
  437.     if (!ret)
  438. {
  439.         /*
  440.          * Open the file of upap secrets and scan for a suitable secret.
  441.          * We don't accept a wildcard client.
  442.          */
  443.         if ((filename = ppp_if[unit]->options->pap_file) != NULL)
  444.             f = fopen(filename, "r");
  445.         if (f == NULL)
  446.             return 0;
  447.         check_access(f, filename);
  448.         i = scan_authfile(f, "", ppp_if[unit]->our_name, secret, &addrs,
  449.       filename);
  450.         ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0;
  451.         fclose(f);
  452.         }
  453.     if (ret) {
  454.         if (ppp_if[unit]->addresses != NULL)
  455.             free_wordlist(ppp_if[unit]->addresses);
  456.         ppp_if[unit]->addresses = addrs;
  457.         }
  458.     return ret;
  459. }
  460. /*
  461.  * get_upap_passwd - get a password for authenticating ourselves with
  462.  * our peer using PAP.  Returns 1 on success, 0 if no suitable password
  463.  * could be found.
  464.  */
  465. static int
  466. get_upap_passwd()
  467. {
  468.     char *filename;
  469.     FILE *f = NULL;
  470.     char secret[MAXWORDLEN];
  471.     if (pppSecretFind (ppp_if[ppp_unit]->user, ppp_if[ppp_unit]->remote_name,
  472. secret, NULL) < 0)
  473.         {
  474.         if ((filename = ppp_if[ppp_unit]->options->pap_file) != NULL)
  475.             f = fopen(filename, "r");
  476.         if (f == NULL)
  477.     return 0;
  478.         check_access(f, filename);
  479.         if (scan_authfile(f, ppp_if[ppp_unit]->user,
  480.     ppp_if[ppp_unit]->remote_name, secret, NULL, filename) < 0)
  481.     {
  482.             fclose(f);
  483.     return 0;
  484.     }
  485.         fclose(f);
  486.         }
  487.     strncpy(ppp_if[ppp_unit]->passwd, secret, MAXSECRETLEN);
  488.     ppp_if[ppp_unit]->passwd[MAXSECRETLEN-1] = 0;
  489.     return 1;
  490. }
  491. /*
  492.  * have_upap_secret - check whether we have a PAP file with any
  493.  * secrets that we could possibly use for authenticating the peer.
  494.  */
  495. static int
  496. have_upap_secret()
  497. {
  498.     FILE *f = NULL;
  499.     int ret;
  500.     char *filename;
  501.     if (ppp_if[ppp_unit]->uselogin)
  502. return 1;
  503.     if (pppSecretFind (NULL, ppp_if[ppp_unit]->our_name, NULL, NULL) < 0)
  504.         {
  505.         if ((filename = ppp_if[ppp_unit]->options->pap_file) != NULL)
  506.             f = fopen(filename, "r");
  507.         if (f == NULL)
  508.     return 0;
  509.         ret = scan_authfile(f, NULL, ppp_if[ppp_unit]->our_name, NULL, NULL,
  510. filename);
  511.         fclose(f);
  512.         if (ret < 0)
  513.     return 0;
  514. }
  515.     return 1;
  516. }
  517. /*
  518.  * have_chap_secret - check whether we have a CHAP file with a
  519.  * secret that we could possibly use for authenticating `client'
  520.  * on `server'.  Either can be the null string, meaning we don't
  521.  * know the identity yet.
  522.  */
  523. static int
  524. have_chap_secret(client, server)
  525.     char *client;
  526.     char *server;
  527. {
  528.     FILE *f = NULL;
  529.     int ret;
  530.     char *filename;
  531.     if (client[0] == 0)
  532.         client = NULL;
  533.     else if (server[0] == 0)
  534.         server = NULL;
  535.     if (pppSecretFind (client, server, NULL, NULL) < 0)
  536. {
  537.         if ((filename = ppp_if[ppp_unit]->options->chap_file) != NULL)
  538.             f = fopen(filename, "r");
  539.         if (f == NULL)
  540.             return 0;
  541.         ret = scan_authfile(f, client, server, NULL, NULL, filename);
  542.         fclose(f);
  543.         if (ret < 0)
  544.     return 0;
  545. }
  546.     return 1;
  547. }
  548. /*
  549.  * get_secret - open the CHAP secret file and return the secret
  550.  * for authenticating the given client on the given server.
  551.  * (We could be either client or server).
  552.  */
  553. int
  554. get_secret(unit, client, server, secret, secret_len, save_addrs)
  555.     int unit;
  556.     char *client;
  557.     char *server;
  558.     char *secret;
  559.     int *secret_len;
  560.     int save_addrs;
  561. {
  562.     FILE *f = NULL;
  563.     int ret, len;
  564.     char *filename;
  565.     struct wordlist *addrs = NULL;
  566.     char secbuf[MAXWORDLEN];
  567.     secbuf[0] = 0;
  568.     if (pppSecretFind (client, server, secbuf, &addrs) < 0)
  569. {
  570.         if ((filename = ppp_if[unit]->options->chap_file) != NULL)
  571.             f = fopen(filename, "r");
  572.         if (f == NULL) {
  573.     syslog(LOG_ERR, "Can't open chap secret file %s", filename);
  574.     return 0;
  575.         }
  576.         check_access(f, filename);
  577.         ret = scan_authfile(f, client, server, secbuf, &addrs, filename);
  578.         fclose(f);
  579.         if (ret < 0)
  580.     return 0;
  581.         }
  582.     if (save_addrs) {
  583. if (ppp_if[unit]->addresses != NULL)
  584.     free_wordlist(ppp_if[unit]->addresses);
  585. ppp_if[unit]->addresses = addrs;
  586.     }
  587.     len = strlen(secbuf);
  588.     if (len > MAXSECRETLEN) {
  589. syslog(LOG_ERR, "Secret for %s on %s is too long", client, server);
  590. len = MAXSECRETLEN;
  591.     }
  592.     BCOPY(secbuf, secret, len);
  593.     *secret_len = len;
  594.     return 1;
  595. }
  596. /*
  597.  * auth_ip_addr - check whether the peer is authorized to use
  598.  * a given IP address.  Returns 1 if authorized, 0 otherwise.
  599.  */
  600. int
  601. auth_ip_addr(unit, addr)
  602.     int unit;
  603.     u_long addr;
  604. {
  605.     u_long a;
  606.     struct wordlist *addrs;
  607.     /* don't allow loopback or multicast address */
  608.     if (bad_ip_adrs(addr))
  609.         return 0;
  610.     if ((addrs = ppp_if[unit]->addresses) == NULL)
  611. return 1; /* no restriction */
  612.     for (; addrs != NULL; addrs = addrs->next) {
  613. /* "-" means no addresses authorized */
  614. if (strcmp(addrs->word, "-") == 0)
  615.     break;
  616. if ((a = inet_addr(addrs->word)) == -1) {
  617.     if ((a = hostGetByName (addrs->word)) == NULL) {
  618. syslog(LOG_WARNING, "unknown host %s in auth. address list",
  619.        addrs->word);
  620. continue;
  621. }
  622. }
  623. if (addr == a)
  624.     return 1;
  625.     }
  626.     return 0; /* not in list => can't have it */
  627. }
  628. /*
  629.  * bad_ip_adrs - return 1 if the IP address is one we don't want
  630.  * to use, such as an address in the loopback net or a multicast address.
  631.  * addr is in network byte order.
  632.  */
  633. int
  634. bad_ip_adrs(addr)
  635.     u_long addr;
  636. {
  637.     addr = ntohl(addr);
  638. #if CPU==SIMSPARCSOLARIS
  639.     return IN_MULTICAST(addr) || IN_BADCLASS(addr);
  640. #else
  641.     return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET
  642.         || IN_MULTICAST(addr) || IN_BADCLASS(addr);
  643. #endif
  644. }
  645. /*
  646.  * check_access - complain if a secret file has too-liberal permissions.
  647.  */
  648. void
  649. check_access(f, fileName)
  650.     FILE *f;
  651.     char *fileName;
  652. {
  653.     struct stat sbuf;
  654.     if (fstat(fileno(f), &sbuf) < 0) {
  655. syslog(LOG_WARNING, "cannot stat secret file %s: %m", fileName);
  656.     } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
  657. syslog(LOG_WARNING, "Warning - secret file %s has world and/or group access", fileName);
  658.     }
  659. }
  660. /*
  661.  * scan_authfile - Scan an authorization file for a secret suitable
  662.  * for authenticating `client' on `server'.  The return value is -1
  663.  * if no secret is found, otherwise >= 0.  The return value has
  664.  * NONWILD_CLIENT set if the secret didn't have "*" for the client, and
  665.  * NONWILD_SERVER set if the secret didn't have "*" for the server.
  666.  * Any following words on the line (i.e. address authorization
  667.  * info) are placed in a wordlist and returned in *addrs.  
  668.  */
  669. static int
  670. scan_authfile(f, client, server, secret, addrs, fileName)
  671.     FILE *f;
  672.     char *client;
  673.     char *server;
  674.     char *secret;
  675.     struct wordlist **addrs;
  676.     char *fileName;
  677. {
  678.     int newline, xxx;
  679.     int got_flag, best_flag;
  680.     FILE *sf;
  681.     struct wordlist *ap, *addr_list, *addr_last;
  682.     char word[MAXWORDLEN];
  683.     char atfile[MAXWORDLEN];
  684.     if (addrs != NULL)
  685. *addrs = NULL;
  686.     addr_list = NULL;
  687.     if (!getword(f, word, &newline, fileName))
  688. return -1; /* file is empty??? */
  689.     newline = 1;
  690.     best_flag = -1;
  691.     for (;;) {
  692. /*
  693.  * Skip until we find a word at the start of a line.
  694.  */
  695. while (!newline && getword(f, word, &newline, fileName))
  696.     ;
  697. if (!newline)
  698.     break; /* got to end of file */
  699. /*
  700.  * Got a client - check if it's a match or a wildcard.
  701.  */
  702. got_flag = 0;
  703. if (client != NULL && client[0] && strcmp(word, client) != 0 &&
  704.     !ISWILD(word)) {
  705.     newline = 0;
  706.     continue;
  707. }
  708. if (!ISWILD(word))
  709.     got_flag = NONWILD_CLIENT;
  710. /*
  711.  * Now get a server and check if it matches.
  712.  */
  713. if (!getword(f, word, &newline, fileName))
  714.     break;
  715. if (newline)
  716.     continue;
  717. if (server != NULL && server[0] && strcmp(word, server) != 0 &&
  718.     !ISWILD(word))
  719.     continue;
  720. if (!ISWILD(word))
  721.     got_flag |= NONWILD_SERVER;
  722. /*
  723.  * Got some sort of a match - see if it's better than what
  724.  * we have already.
  725.  */
  726. if (got_flag <= best_flag)
  727.     continue;
  728. /*
  729.  * Get the secret.
  730.  */
  731. if (!getword(f, word, &newline, fileName))
  732.     break;
  733. if (newline)
  734.     continue;
  735. /*
  736.  * Special syntax: @filename means read secret from file.
  737.  */
  738. if (word[0] == '@') {
  739.     strcpy(atfile, word+1);
  740.     if ((sf = fopen(atfile, "r")) == NULL) {
  741. syslog(LOG_WARNING, "can't open indirect secret file %s",
  742.                        atfile);
  743. continue;
  744.     }
  745.     check_access(sf, atfile);
  746.     if (!getword(sf, word, &xxx, atfile)) {
  747. syslog(LOG_WARNING, "no secret in indirect secret file %s",
  748.                        atfile);
  749. fclose(sf);
  750. continue;
  751.     }
  752.     fclose(sf);
  753. }
  754. if (secret != NULL)
  755.     strcpy(secret, word);
  756. best_flag = got_flag;
  757. /*
  758.  * Now read address authorization info and make a wordlist.
  759.  */
  760. if (addr_list)
  761.     free_wordlist(addr_list);
  762. addr_list = addr_last = NULL;
  763. for (;;) {
  764.     if (!getword(f, word, &newline, fileName) || newline)
  765. break;
  766.     ap = (struct wordlist *) malloc(sizeof(struct wordlist)
  767.     + strlen(word));
  768.     if (ap == NULL)
  769. novm("authorized addresses");
  770.     ap->next = NULL;
  771.     strcpy(ap->word, word);
  772.     if (addr_list == NULL)
  773. addr_list = ap;
  774.     else
  775. addr_last->next = ap;
  776.     addr_last = ap;
  777. }
  778. if (!newline)
  779.     break;
  780.     }
  781.     if (addrs != NULL)
  782. *addrs = addr_list;
  783.     else if (addr_list != NULL)
  784. free_wordlist(addr_list);
  785.     return best_flag;
  786. }
  787. /*
  788.  * free_wordlist - release memory allocated for a wordlist.
  789.  */
  790. static void
  791. free_wordlist(wp)
  792.     struct wordlist *wp;
  793. {
  794.     struct wordlist *next;
  795.     while (wp != NULL) {
  796. next = wp->next;
  797. free(wp);
  798. wp = next;
  799.     }
  800. }