Пример #1
0
/*
 * rad_continue_send_request() has given us `got' (non-zero).  Deal with it.
 */
static void
radius_Process(struct radius *r, int got)
{
  char *argv[MAXARGS], *nuke;
  struct bundle *bundle;
  int argc, addrs, res, width;
  size_t len;
  struct ncprange dest;
  struct ncpaddr gw;
  const void *data;
  const char *stype;
  u_int32_t ipaddr, vendor;
  struct in_addr ip;
#ifndef NOINET6
  uint8_t ipv6addr[INET6_ADDRSTRLEN];
  struct in6_addr ip6;
#endif

  r->cx.fd = -1;		/* Stop select()ing */
  stype = r->cx.auth ? "auth" : "acct";

  switch (got) {
    case RAD_ACCESS_ACCEPT:
      log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		 "Radius(%s): ACCEPT received\n", stype);
      if (!r->cx.auth) {
        rad_close(r->cx.rad);
        return;
      }
      break;

    case RAD_ACCESS_REJECT:
      log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		 "Radius(%s): REJECT received\n", stype);
      if (!r->cx.auth) {
        rad_close(r->cx.rad);
        return;
      }
      break;

    case RAD_ACCESS_CHALLENGE:
      /* we can't deal with this (for now) ! */
      log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		 "Radius: CHALLENGE received (can't handle yet)\n");
      if (r->cx.auth)
        auth_Failure(r->cx.auth);
      rad_close(r->cx.rad);
      return;

    case RAD_ACCOUNTING_RESPONSE:
      /*
       * It's probably not ideal to log this at PHASE level as we'll see
       * too much stuff going to the log when ``set rad_alive'' is used.
       * So we differ from older behaviour (ppp version 3.1 and before)
       * and just log accounting responses to LogRADIUS.
       */
      log_Printf(LogRADIUS, "Radius(%s): Accounting response received\n",
		 stype);
      if (r->cx.auth)
        auth_Failure(r->cx.auth);		/* unexpected !!! */

      /* No further processing for accounting requests, please */
      rad_close(r->cx.rad);
      return;

    case -1:
      log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		 "radius(%s): %s\n", stype, rad_strerror(r->cx.rad));
      if (r->cx.auth)
        auth_Failure(r->cx.auth);
      rad_close(r->cx.rad);
      return;

    default:
      log_Printf(LogERROR, "rad_send_request(%s): Failed %d: %s\n", stype,
                 got, rad_strerror(r->cx.rad));
      if (r->cx.auth)
        auth_Failure(r->cx.auth);
      rad_close(r->cx.rad);
      return;
  }

  /* Let's see what we've got in our reply */
  r->ip.s_addr = r->mask.s_addr = INADDR_NONE;
  r->mtu = 0;
  r->vj = 0;
  while ((res = rad_get_attr(r->cx.rad, &data, &len)) > 0) {
    switch (res) {
      case RAD_FRAMED_IP_ADDRESS:
        r->ip = rad_cvt_addr(data);
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " IP %s\n", inet_ntoa(r->ip));
        break;

      case RAD_FILTER_ID:
        free(r->filterid);
        if ((r->filterid = rad_cvt_string(data, len)) == NULL) {
          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Filter \"%s\"\n", r->filterid);
        break;

      case RAD_SESSION_TIMEOUT:
        r->sessiontime = rad_cvt_int(data);
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Session-Timeout %lu\n", r->sessiontime);
        break;

      case RAD_FRAMED_IP_NETMASK:
        r->mask = rad_cvt_addr(data);
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Netmask %s\n", inet_ntoa(r->mask));
        break;

      case RAD_FRAMED_MTU:
        r->mtu = rad_cvt_int(data);
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " MTU %lu\n", r->mtu);
        break;

      case RAD_FRAMED_ROUTING:
        /* Disabled for now - should we automatically set up some filters ? */
        /* rad_cvt_int(data); */
        /* bit 1 = Send routing packets */
        /* bit 2 = Receive routing packets */
        break;

      case RAD_FRAMED_COMPRESSION:
        r->vj = rad_cvt_int(data) == 1 ? 1 : 0;
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " VJ %sabled\n", r->vj ? "en" : "dis");
        break;

      case RAD_FRAMED_ROUTE:
        /*
         * We expect a string of the format ``dest[/bits] gw [metrics]''
         * Any specified metrics are ignored.  MYADDR and HISADDR are
         * understood for ``dest'' and ``gw'' and ``0.0.0.0'' is the same
         * as ``HISADDR''.
         */

        if ((nuke = rad_cvt_string(data, len)) == NULL) {
          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }

	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Route: %s\n", nuke);
        bundle = r->cx.auth->physical->dl->bundle;
        ip.s_addr = INADDR_ANY;
        ncpaddr_setip4(&gw, ip);
        ncprange_setip4host(&dest, ip);
        argc = command_Interpret(nuke, strlen(nuke), argv);
        if (argc < 0)
          log_Printf(LogWARN, "radius: %s: Syntax error\n",
                     argc == 1 ? argv[0] : "\"\"");
        else if (argc < 2)
          log_Printf(LogWARN, "radius: %s: Invalid route\n",
                     argc == 1 ? argv[0] : "\"\"");
        else if ((strcasecmp(argv[0], "default") != 0 &&
                  !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
                 !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
          log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
                     argv[0], argv[1]);
        else {
          ncprange_getwidth(&dest, &width);
          if (width == 32 && strchr(argv[0], '/') == NULL) {
            /* No mask specified - use the natural mask */
            ncprange_getip4addr(&dest, &ip);
            ncprange_setip4mask(&dest, addr2mask(ip));
          }
          addrs = 0;

          if (!strncasecmp(argv[0], "HISADDR", 7))
            addrs = ROUTE_DSTHISADDR;
          else if (!strncasecmp(argv[0], "MYADDR", 6))
            addrs = ROUTE_DSTMYADDR;

          if (ncpaddr_getip4addr(&gw, &ipaddr) && ipaddr == INADDR_ANY) {
            addrs |= ROUTE_GWHISADDR;
            ncpaddr_setip4(&gw, bundle->ncp.ipcp.peer_ip);
          } else if (strcasecmp(argv[1], "HISADDR") == 0)
            addrs |= ROUTE_GWHISADDR;

          route_Add(&r->routes, addrs, &dest, &gw);
        }
        free(nuke);
        break;

      case RAD_REPLY_MESSAGE:
        free(r->repstr);
        if ((r->repstr = rad_cvt_string(data, len)) == NULL) {
          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " Reply-Message \"%s\"\n", r->repstr);
        break;

#ifndef NOINET6
      case RAD_FRAMED_IPV6_PREFIX:
	free(r->ipv6prefix);
	if ((r->ipv6prefix = rad_cvt_ipv6prefix(data, len)) == NULL) {
	  log_Printf(LogERROR, "rad_cvt_ipv6prefix: %s\n",
		     "Malformed attribute in response");
	  auth_Failure(r->cx.auth);
	  rad_close(r->cx.rad);
	  return;
	}
	inet_ntop(AF_INET6, &r->ipv6prefix[2], ipv6addr, sizeof(ipv6addr));
	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " IPv6 %s/%d\n", ipv6addr, r->ipv6prefix[1]);
        break;

      case RAD_FRAMED_IPV6_ROUTE:
        /*
         * We expect a string of the format ``dest[/bits] gw [metrics]''
         * Any specified metrics are ignored.  MYADDR6 and HISADDR6 are
         * understood for ``dest'' and ``gw'' and ``::'' is the same
         * as ``HISADDR6''.
         */

        if ((nuke = rad_cvt_string(data, len)) == NULL) {
          log_Printf(LogERROR, "rad_cvt_string: %s\n", rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }

	log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
		   " IPv6 Route: %s\n", nuke);
        bundle = r->cx.auth->physical->dl->bundle;
	ncpaddr_setip6(&gw, &in6addr_any);
	ncprange_set(&dest, &gw, 0);
        argc = command_Interpret(nuke, strlen(nuke), argv);
        if (argc < 0)
          log_Printf(LogWARN, "radius: %s: Syntax error\n",
                     argc == 1 ? argv[0] : "\"\"");
        else if (argc < 2)
          log_Printf(LogWARN, "radius: %s: Invalid route\n",
                     argc == 1 ? argv[0] : "\"\"");
        else if ((strcasecmp(argv[0], "default") != 0 &&
                  !ncprange_aton(&dest, &bundle->ncp, argv[0])) ||
                 !ncpaddr_aton(&gw, &bundle->ncp, argv[1]))
          log_Printf(LogWARN, "radius: %s %s: Invalid route\n",
                     argv[0], argv[1]);
        else {
          addrs = 0;

          if (!strncasecmp(argv[0], "HISADDR6", 8))
            addrs = ROUTE_DSTHISADDR6;
          else if (!strncasecmp(argv[0], "MYADDR6", 7))
            addrs = ROUTE_DSTMYADDR6;

          if (ncpaddr_getip6(&gw, &ip6) && IN6_IS_ADDR_UNSPECIFIED(&ip6)) {
            addrs |= ROUTE_GWHISADDR6;
            ncpaddr_copy(&gw, &bundle->ncp.ipv6cp.hisaddr);
          } else if (strcasecmp(argv[1], "HISADDR6") == 0)
            addrs |= ROUTE_GWHISADDR6;

          route_Add(&r->ipv6routes, addrs, &dest, &gw);
        }
        free(nuke);
        break;
#endif

      case RAD_VENDOR_SPECIFIC:
        if ((res = rad_get_vendor_attr(&vendor, &data, &len)) <= 0) {
          log_Printf(LogERROR, "rad_get_vendor_attr: %s (failing!)\n",
                     rad_strerror(r->cx.rad));
          auth_Failure(r->cx.auth);
          rad_close(r->cx.rad);
          return;
        }

	switch (vendor) {
          case RAD_VENDOR_MICROSOFT:
            switch (res) {
#ifndef NODES
              case RAD_MICROSOFT_MS_CHAP_ERROR:
                free(r->errstr);
                if (len == 0)
                  r->errstr = NULL;
                else {
                  if (len < 3 || ((const char *)data)[1] != '=') {
                    /*
                     * Only point at the String field if we don't think the
                     * peer has misformatted the response.
                     */
                    data = (const char *)data + 1;
                    len--;
                  } else
                    log_Printf(LogWARN, "Warning: The MS-CHAP-Error "
                               "attribute is mis-formatted.  Compensating\n");
                  if ((r->errstr = rad_cvt_string((const char *)data,
                                                  len)) == NULL) {
                    log_Printf(LogERROR, "rad_cvt_string: %s\n",
                               rad_strerror(r->cx.rad));
                    auth_Failure(r->cx.auth);
                    rad_close(r->cx.rad);
                    return;
                  }
		  log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			     " MS-CHAP-Error \"%s\"\n", r->errstr);
                }
                break;

              case RAD_MICROSOFT_MS_CHAP2_SUCCESS:
                free(r->msrepstr);
                if (len == 0)
                  r->msrepstr = NULL;
                else {
                  if (len < 3 || ((const char *)data)[1] != '=') {
                    /*
                     * Only point at the String field if we don't think the
                     * peer has misformatted the response.
                     */
                    data = (const char *)data + 1;
                    len--;
                  } else
                    log_Printf(LogWARN, "Warning: The MS-CHAP2-Success "
                               "attribute is mis-formatted.  Compensating\n");
                  if ((r->msrepstr = rad_cvt_string((const char *)data,
                                                    len)) == NULL) {
                    log_Printf(LogERROR, "rad_cvt_string: %s\n",
                               rad_strerror(r->cx.rad));
                    auth_Failure(r->cx.auth);
                    rad_close(r->cx.rad);
                    return;
                  }
		  log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			     " MS-CHAP2-Success \"%s\"\n", r->msrepstr);
                }
                break;

              case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_POLICY:
                r->mppe.policy = rad_cvt_int(data);
		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			   " MS-MPPE-Encryption-Policy %s\n",
                           radius_policyname(r->mppe.policy));
                break;

              case RAD_MICROSOFT_MS_MPPE_ENCRYPTION_TYPES:
                r->mppe.types = rad_cvt_int(data);
		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			   " MS-MPPE-Encryption-Types %s\n",
                           radius_typesname(r->mppe.types));
                break;

              case RAD_MICROSOFT_MS_MPPE_RECV_KEY:
                free(r->mppe.recvkey);
		demangle(r, data, len, &r->mppe.recvkey, &r->mppe.recvkeylen);
		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			   " MS-MPPE-Recv-Key ********\n");
                break;

              case RAD_MICROSOFT_MS_MPPE_SEND_KEY:
		demangle(r, data, len, &r->mppe.sendkey, &r->mppe.sendkeylen);
		log_Printf(log_IsKept(LogRADIUS) ? LogRADIUS : LogPHASE,
			   " MS-MPPE-Send-Key ********\n");
                break;
#endif

              default:
                log_Printf(LogDEBUG, "Dropping MICROSOFT vendor specific "
                           "RADIUS attribute %d\n", res);
                break;
            }
            break;

          default:
            log_Printf(LogDEBUG, "Dropping vendor %lu RADIUS attribute %d\n",
                       (unsigned long)vendor, res);
            break;
        }
        break;

      default:
        log_Printf(LogDEBUG, "Dropping RADIUS attribute %d\n", res);
        break;
    }
  }

  if (res == -1) {
    log_Printf(LogERROR, "rad_get_attr: %s (failing!)\n",
               rad_strerror(r->cx.rad));
    auth_Failure(r->cx.auth);
  } else if (got == RAD_ACCESS_REJECT)
    auth_Failure(r->cx.auth);
  else {
    r->valid = 1;
    auth_Success(r->cx.auth);
  }
  rad_close(r->cx.rad);
}
Пример #2
0
int
iface_Show(struct cmdargs const *arg)
{
  struct ncpaddr ncpaddr;
  struct iface *iface = arg->bundle->iface, *current;
  unsigned f;
  int flags;
#ifndef NOINET6
  int scopeid, width;
#endif
  struct in_addr mask;

  current = iface_Create(iface->name);
  flags = iface->flags = current->flags;
  iface_Free(current);

  prompt_Printf(arg->prompt, "%s (idx %d) <", iface->name, iface->index);
  for (f = 0; f < sizeof if_flags / sizeof if_flags[0]; f++)
    if ((if_flags[f].flag & flags)) {
      prompt_Printf(arg->prompt, "%s%s", flags == iface->flags ? "" : ",",
                    if_flags[f].value);
      flags &= ~if_flags[f].flag;
    }

#if 0
  if (flags)
    prompt_Printf(arg->prompt, "%s0x%x", flags == iface->flags ? "" : ",",
                  flags);
#endif

  prompt_Printf(arg->prompt, "> mtu %lu has %d address%s:\n", iface->mtu,
                iface->addrs, iface->addrs == 1 ? "" : "es");

  for (f = 0; f < iface->addrs; f++) {
    ncprange_getaddr(&iface->addr[f].ifa, &ncpaddr);
    switch (ncprange_family(&iface->addr[f].ifa)) {
    case AF_INET:
      prompt_Printf(arg->prompt, "  inet %s --> ", ncpaddr_ntoa(&ncpaddr));
      if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC)
        prompt_Printf(arg->prompt, "255.255.255.255");
      else
        prompt_Printf(arg->prompt, "%s", ncpaddr_ntoa(&iface->addr[f].peer));
      ncprange_getip4mask(&iface->addr[f].ifa, &mask);
      prompt_Printf(arg->prompt, " netmask 0x%08lx", (long)ntohl(mask.s_addr));
      break;

#ifndef NOINET6
    case AF_INET6:
      prompt_Printf(arg->prompt, "  inet6 %s", ncpaddr_ntoa(&ncpaddr));
      if (ncpaddr_family(&iface->addr[f].peer) != AF_UNSPEC)
        prompt_Printf(arg->prompt, " --> %s",
                      ncpaddr_ntoa(&iface->addr[f].peer));
      ncprange_getwidth(&iface->addr[f].ifa, &width);
      if (ncpaddr_family(&iface->addr[f].peer) == AF_UNSPEC)
        prompt_Printf(arg->prompt, " prefixlen %d", width);
      if ((scopeid = ncprange_scopeid(&iface->addr[f].ifa)) != -1)
        prompt_Printf(arg->prompt, " scopeid 0x%x", (unsigned)scopeid);
      break;
#endif
    }
    prompt_Printf(arg->prompt, "\n");
  }

  return 0;
}
Пример #3
0
static int
filter_Parse(struct ncp *ncp, int argc, char const *const *argv,
             struct filterent *ofp)
{
  struct filterent fe;
  struct protoent *pe;
  char *wp;
  int action, family, ruleno, val, width;

  ruleno = strtol(*argv, &wp, 0);
  if (*argv == wp || ruleno >= MAXFILTERS) {
    log_Printf(LogWARN, "Parse: invalid filter number.\n");
    return 0;
  }
  if (ruleno < 0) {
    for (ruleno = 0; ruleno < MAXFILTERS; ruleno++) {
      ofp->f_action = A_NONE;
      ofp++;
    }
    log_Printf(LogWARN, "Parse: filter cleared.\n");
    return 1;
  }
  ofp += ruleno;

  if (--argc == 0) {
    log_Printf(LogWARN, "Parse: missing action.\n");
    return 0;
  }
  argv++;

  memset(&fe, '\0', sizeof fe);

  val = strtol(*argv, &wp, 0);
  if (!*wp && val >= 0 && val < MAXFILTERS) {
    if (val <= ruleno) {
      log_Printf(LogWARN, "Parse: Can only jump forward from rule %d\n",
                 ruleno);
      return 0;
    }
    action = val;
  } else if (!strcmp(*argv, "permit")) {
    action = A_PERMIT;
  } else if (!strcmp(*argv, "deny")) {
    action = A_DENY;
  } else if (!strcmp(*argv, "clear")) {
    ofp->f_action = A_NONE;
    return 1;
  } else {
    log_Printf(LogWARN, "Parse: %s: bad action\n", *argv);
    return 0;
  }
  fe.f_action = action;

  argc--;
  argv++;

  if (argc && argv[0][0] == '!' && !argv[0][1]) {
    fe.f_invert = 1;
    argc--;
    argv++;
  }

  ncprange_init(&fe.f_src);
  ncprange_init(&fe.f_dst);

  if (argc == 0)
    pe = NULL;
  else if ((pe = getprotobyname(*argv)) == NULL && strcmp(*argv, "all") != 0) {
    if (argc < 2) {
      log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
      return 0;
    } else if (strcasecmp(*argv, "any") == 0 ||
               ncprange_aton(&fe.f_src, ncp, *argv)) {
      family = ncprange_family(&fe.f_src);
      if (!ncprange_getwidth(&fe.f_src, &width))
        width = 0;
      if (width == 0)
        ncprange_init(&fe.f_src);
      fe.f_srctype = addrtype(*argv);
      argc--;
      argv++;

      if (strcasecmp(*argv, "any") == 0 ||
          ncprange_aton(&fe.f_dst, ncp, *argv)) {
        if (ncprange_family(&fe.f_dst) != AF_UNSPEC &&
            ncprange_family(&fe.f_src) != AF_UNSPEC &&
            family != ncprange_family(&fe.f_dst)) {
          log_Printf(LogWARN, "Parse: src and dst address families differ\n");
          return 0;
        }
        if (!ncprange_getwidth(&fe.f_dst, &width))
          width = 0;
        if (width == 0)
          ncprange_init(&fe.f_dst);
        fe.f_dsttype = addrtype(*argv);
        argc--;
        argv++;
      } else {
        log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
        return 0;
      }

      if (argc) {
        if ((pe = getprotobyname(*argv)) == NULL && strcmp(*argv, "all") != 0) {
          log_Printf(LogWARN, "Parse: %s: Protocol expected\n", *argv);
          return 0;
        } else {
          argc--;
          argv++;
        }
      }
    } else {
      log_Printf(LogWARN, "Parse: Protocol or address pair expected\n");
      return 0;
    }
  } else {
    argc--;
    argv++;
  }

  if (argc >= 2 && strcmp(*argv, "timeout") == 0) {
    fe.timeout = strtoul(argv[1], NULL, 10);
    argc -= 2;
    argv += 2;
  }

  val = 1;
  fe.f_proto = (pe == NULL) ? 0 : pe->p_proto;

  switch (fe.f_proto) {
  case IPPROTO_TCP:
  case IPPROTO_UDP:
  case IPPROTO_IPIP:
#ifndef NOINET6
  case IPPROTO_IPV6:
#endif
    val = ParseUdpOrTcp(argc, argv, pe, &fe);
    break;
  case IPPROTO_ICMP:
#ifndef NOINET6
  case IPPROTO_ICMPV6:
#endif
    val = ParseIcmp(argc, argv, &fe);
    break;
  default:
    val = ParseGeneric(argc, &fe);
    break;
  }

  log_Printf(LogDEBUG, "Parse: Src: %s\n", ncprange_ntoa(&fe.f_src));
  log_Printf(LogDEBUG, "Parse: Dst: %s\n", ncprange_ntoa(&fe.f_dst));
  log_Printf(LogDEBUG, "Parse: Proto: %d\n", fe.f_proto);

  log_Printf(LogDEBUG, "Parse: src:  %s (%d)\n",
            filter_Op2Nam(fe.f_srcop), fe.f_srcport);
  log_Printf(LogDEBUG, "Parse: dst:  %s (%d)\n",
            filter_Op2Nam(fe.f_dstop), fe.f_dstport);
  log_Printf(LogDEBUG, "Parse: estab: %u\n", fe.f_estab);
  log_Printf(LogDEBUG, "Parse: syn: %u\n", fe.f_syn);
  log_Printf(LogDEBUG, "Parse: finrst: %u\n", fe.f_finrst);

  if (val)
    *ofp = fe;

  return val;
}