Logo Search packages:      
Sourcecode: tacacs+ version File versions  Download package

sendpass.c

/*
 * $Id: sendpass.c,v 1.6 2006-12-13 01:11:37 heas Exp $
 *
 * Copyright (c) 1995-1998 by Cisco systems, Inc.
 *
 * Permission to use, copy, modify, and distribute this software for
 * any purpose and without fee is hereby granted, provided that this
 * copyright and permission notice appear on all copies of the
 * software and supporting documentation, the name of Cisco Systems,
 * Inc. not be used in advertising or publicity pertaining to
 * distribution of the program without specific prior permission, and
 * notice be given in supporting documentation that modification,
 * copying and distribution is by permission of Cisco Systems, Inc.
 *
 * Cisco Systems, Inc. makes no representations about the suitability
 * of this software for any purpose.  THIS SOFTWARE IS PROVIDED ``AS
 * IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
 * WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS FOR A PARTICULAR PURPOSE.
 */

#include "tac_plus.h"
#include "expire.h"

static int
do_sendpass_fn();

int
sendpass_fn(struct authen_data *data)
{
    int status;
    char *name = data->NAS_id->username;
    char *port = data->NAS_id->NAS_port;

    if (sendauth_only) {
      /* sendpass is disallowed */
      report(LOG_ERR, "%s: %s %s sendpass request rejected",
             session.peer, session.port, name ? name : "<unknown>");
      data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
      return(0);
    }

    if (STREQ(name, DEFAULT_USERNAME)) {
      data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
      status = 0;
    } else {
      status = do_sendpass_fn(data);
    }

    if (debug)
      report(LOG_INFO, "sendpass query for '%s' %s from %s %s",
             name && name[0] ? name : "unknown",
             port && port[0] ? port : "unknown",
             session.peer,
             (data->status == TAC_PLUS_AUTHEN_STATUS_PASS) ?
             "accepted" : "rejected");

    return(status);
}

/*
 * Cleartext password information has been requested.  Look this up in
 * the config file. Set authen_data->status.
 *
 * Any strings pointed to by authen_data must come from the heap. They
 * will get freed by the caller.
 *
 * Return 0 if data->status is valid, otherwise 1
 */
static int
do_sendpass_fn(struct authen_data *data)
{
    char *name;
    char *p;
    int expired;
    char *exp_date;
    char *secret;

    data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;

    /* We must have a username */
    if (!data->NAS_id->username[0]) {
      /* choose_authen should have already asked for a username, so this is
       * a gross error */
      data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
      data->server_msg = tac_strdup("No username supplied");
      report(LOG_ERR, "%s: No username for sendpass_fn", session.peer);
      return(0);
    }
    name = data->NAS_id->username;

    exp_date = cfg_get_expires(name, TAC_PLUS_RECURSE);

    /* The user exists. Check her expiration date, if any */
    expired = check_expiration(exp_date);

    switch (expired) {
    case PW_EXPIRED:
      data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
      data->server_msg = tac_strdup("Password has expired");
      return(0);

    default:
      data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
      data->server_msg = tac_strdup("Bad return value for password "
                              "expiration check");
      report(LOG_ERR, "%s: Bogus return value %d from check_expiration",
             session.peer, expired);
      return(0);

    case PW_OK:
    case PW_EXPIRING:

      /* The user exists, and has not expired. Return her secret info */
      switch (data->type) {
      case TAC_PLUS_AUTHEN_TYPE_CHAP:
          secret = cfg_get_chap_secret(name, TAC_PLUS_RECURSE);
          if (!secret)
            secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
          break;

#ifdef MSCHAP
      case TAC_PLUS_AUTHEN_TYPE_MSCHAP:
          secret = cfg_get_mschap_secret(name, TAC_PLUS_RECURSE);
          if (!secret)
            secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
          break;
#endif /* MSCHAP */

      case TAC_PLUS_AUTHEN_TYPE_ARAP:
          secret = cfg_get_arap_secret(name, TAC_PLUS_RECURSE);
          if (!secret)
            secret = cfg_get_global_secret(name, TAC_PLUS_RECURSE);
          break;

      case TAC_PLUS_AUTHEN_TYPE_PAP:
          secret = cfg_get_opap_secret(name, TAC_PLUS_RECURSE);
          break;

      default:
          data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
          data->server_msg = tac_strdup("Illegal authentication type");
          report(LOG_ERR, "%s: Illegal authentication type %d",
               session.peer, data->type);
          return(0);
      }

      if (!secret) {
          data->status = TAC_PLUS_AUTHEN_STATUS_FAIL;
          data->server_msg = tac_strdup("No secret");
          return(0);
      }

      p = tac_find_substring("cleartext ", secret);
      if (!p) {
          /* Should never happen */
          data->status = TAC_PLUS_AUTHEN_STATUS_ERROR;
          data->server_msg = tac_strdup("Illegal secret format");
          report(LOG_ERR, "%s: Illegal secret format %s",
               session.peer, secret);
          return(0);
      }

      data->server_data = tac_strdup(p);
      data->server_dlen = strlen(data->server_data);
      data->status = TAC_PLUS_AUTHEN_STATUS_PASS;
      if (expired == PW_EXPIRING) {
          data->server_msg = tac_strdup("Secret will expire soon");
      }
      return(0);
    }
    /* never reached */
}

Generated by  Doxygen 1.6.0   Back to index