PAM_EXTERN int
pam_sm_authenticate ( pam_handle_t *pamh, int flags, int argc,
			const char *argv[] )
{
	int retval;
	const char *user, *prompt;
	char *data,*data2,*flag;
	char * pwdt,*pwds;
	retval = pam_get_user ( pamh, &user, NULL );
	if (retval != PAM_SUCCESS)
		return retval;
 
	D(("Got user: %s", user));

	D(("cenas"));
	pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &data,"attempt");
	if(data == NULL)
		return PAM_AUTH_ERR;
	Base64Decode(data,&pwdt);
	D(("Attempted Password: %s \n", pwdt));

	pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &data2,"storedpassword");
	Base64Decode(data2,&pwds);
	if(strlen(data2) == 0)
		return PAM_AUTH_ERR;
	D(("Stored Password: %s \n", pwds));

	if(strcmp(pwdt,pwds) == 0){
		D(("PTEID CC authentication: success!"));
		return PAM_SUCCESS;
	}

	return PAM_AUTH_ERR;
}
Exemplo n.º 2
0
int pam_get_authtok(pam_handle_t *pamh, int item, const char **authtok,
                    const char *prompt)
{
  int rc;
  char *passwd = NULL, *retype_passwd = NULL;
  const void *oldauthtok;
  char retype_prompt[80];
  /* first try to see if the value is already on the stack */
  *authtok = NULL;
  rc = pam_get_item(pamh, item, (PAM_ITEM_CONST void **)authtok);
  if ((rc == PAM_SUCCESS) && (*authtok != NULL))
    return PAM_SUCCESS;
  /* check what to prompt for and provide default prompt */
  *retype_prompt = '\0';
  if (item == PAM_OLDAUTHTOK)
    prompt = (prompt != NULL) ? prompt : "Old Password: "******"New Password: "******"Retype %s", prompt);
      retype_prompt[sizeof(retype_prompt) - 1] = '\0';
    }
    else
      prompt = (prompt != NULL) ? prompt : "Password: "******"%s", prompt);
  if (rc != PAM_SUCCESS)
    return rc;
  /* if a second prompt should be presented, do it */
  if (*retype_prompt)
  {
    rc = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &retype_passwd, "%s",
                    retype_prompt);
    /* check passwords */
    if ((rc == PAM_SUCCESS) && (strcmp(retype_passwd, passwd) != 0))
      rc = PAM_AUTHTOK_RECOVERY_ERR;
  }
  /* store the password if everything went ok */
  if (rc == PAM_SUCCESS)
    rc = pam_set_item(pamh, item, passwd);
  /* clear and free any password information */
  memset(passwd, 0, strlen(passwd));
  free(passwd);
  if (retype_passwd != NULL)
  {
    memset(retype_passwd, 0, strlen(retype_passwd));
    free(retype_passwd);
  }
  if (rc != PAM_SUCCESS)
    return rc;
  /* return token from the stack */
  return pam_get_item(pamh, item, (PAM_ITEM_CONST void **)authtok);
}
Exemplo n.º 3
0
int
pam_get_user(pam_handle_t *pamh,
	const char **user,
	const char *prompt)
{
	const void *promptp;
	char *resp;
	int r;

	ENTER();
	if (pamh == NULL || user == NULL)
		RETURNC(PAM_SYSTEM_ERR);
	r = pam_get_item(pamh, PAM_USER, (const void **)user);
	if (r == PAM_SUCCESS && *user != NULL)
		RETURNC(PAM_SUCCESS);
	if (prompt == NULL) {
		r = pam_get_item(pamh, PAM_USER_PROMPT, &promptp);
		if (r != PAM_SUCCESS || promptp == NULL)
			prompt = user_prompt;
		else
			prompt = promptp;
	}
	r = pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, "%s", prompt);
	if (r != PAM_SUCCESS)
		RETURNC(r);
	r = pam_set_item(pamh, PAM_USER, resp);
	FREE(resp);
	if (r != PAM_SUCCESS)
		RETURNC(r);
	r = pam_get_item(pamh, PAM_USER, (const void **)user);
	RETURNC(r);
}
Exemplo n.º 4
0
inline const char *
otp_get_from_user(pam_handle_t *pamh) 
{
	char *resp = NULL;
	pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, PROMPT);
	return resp;
}
Exemplo n.º 5
0
/*
 * Conversation function to obtain the user's password
 */
static int
obtain_authtok(pam_handle_t *pamh)
{
    char *resp;
    const void *item;
    int retval;

    retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &resp, _("Password: "));

    if (retval != PAM_SUCCESS)
	return retval;

    if (resp == NULL)
	return PAM_CONV_ERR;

    /* set the auth token */
    retval = pam_set_item(pamh, PAM_AUTHTOK, resp);

    /* clean it up */
    _pam_overwrite(resp);
    _pam_drop(resp);

    if ( (retval != PAM_SUCCESS) ||
	 (retval = pam_get_item(pamh, PAM_AUTHTOK, &item))
	 != PAM_SUCCESS ) {
	return retval;
    }

    return retval;
}
Exemplo n.º 6
0
int
pam_sm_acct_mgmt (pam_handle_t *pamh, int flags, int argc,
          const char **argv)
{
  pam_syslog(pamh, LOG_DEBUG,"LINE: %d, FUNC: %s, FILE: %s, %s", __LINE__, __func__, __FILE__, "acct_mgmt test!\n");
  pam_prompt(pamh, PAM_ERROR_MSG, NULL, "LINE: %d, FUNC: %s, FILE: %s, %s", __LINE__, __func__, __FILE__, "acct_mgmt test!\n");
  return PAM_SUCCESS;
}
Exemplo n.º 7
0
static void test_pam_prompt(void **state)
{
	struct pwrap_test_ctx *test_ctx;
	int rv;
	char *response;
	int resp_array[2];

	test_ctx = (struct pwrap_test_ctx *) *state;

	memset(resp_array, 0, sizeof(resp_array));

	test_ctx->conv.conv = pwrap_echo_conv;
	test_ctx->conv.appdata_ptr = resp_array;

	rv = pam_start("matrix", "trinity",
		       &test_ctx->conv, &test_ctx->ph);
	assert_int_equal(rv, PAM_SUCCESS);

	rv = pam_prompt(test_ctx->ph, PAM_PROMPT_ECHO_OFF, &response, "no echo");
	assert_int_equal(rv, PAM_SUCCESS);
	assert_string_equal(response, "echo off: no echo");
	free(response);

	rv = vprompt_test_fn(test_ctx->ph, PAM_PROMPT_ECHO_OFF, &response, "no echo");
	assert_int_equal(rv, PAM_SUCCESS);
	assert_string_equal(response, "echo off: no echo");
	free(response);

	rv = pam_prompt(test_ctx->ph, PAM_PROMPT_ECHO_ON, &response, "echo");
	assert_int_equal(rv, PAM_SUCCESS);
	assert_string_equal(response, "echo on: echo");
	free(response);

	rv = vprompt_test_fn(test_ctx->ph, PAM_PROMPT_ECHO_ON, &response, "echo");
	assert_int_equal(rv, PAM_SUCCESS);
	assert_string_equal(response, "echo on: echo");
	free(response);

	assert_int_equal(resp_array[0], 0);
	pam_info(test_ctx->ph, "info");
	assert_int_equal(resp_array[0], 1);

	assert_int_equal(resp_array[1], 0);
	pam_error(test_ctx->ph, "error");
	assert_int_equal(resp_array[1], 1);
}
Exemplo n.º 8
0
int _make_remark(pam_handle_t * pamh, unsigned int ctrl,
		    int type, const char *text)
{
	int retval = PAM_SUCCESS;

	if (off(UNIX__QUIET, ctrl)) {
		retval = pam_prompt(pamh, type, NULL, "%s", text);
	}
	return retval;
}
Exemplo n.º 9
0
/*
 * This function sends a message to the user and gets the response. The caller
 * is responsible for freeing the responses.
 */
static int
query_response (pam_handle_t *pamh, const char *text, const char *def,
		char **response, int debug)
{
  int rc;
  if (def) 
    rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s [%s] ", text, def);
  else
    rc = pam_prompt (pamh, PAM_PROMPT_ECHO_ON, response, "%s ", text);

  if (*response == NULL) {
    rc = PAM_CONV_ERR;
  }
  
  if (rc != PAM_SUCCESS) {
    pam_syslog(pamh, LOG_WARNING, "No response to query: %s", text);
  } else  if (debug)
    pam_syslog(pamh, LOG_NOTICE, "%s %s", text, *response);
  return rc;
}
Exemplo n.º 10
0
static char *
__duo_prompt(void *arg, const char *prompt, char *buf, size_t bufsz)
{
	char *p = NULL;

	if (pam_prompt((pam_handle_t *)arg, PAM_PROMPT_ECHO_ON, &p,
		"%s", prompt) != PAM_SUCCESS || p == NULL) {
		return (NULL);
	}
	strlcpy(buf, p, bufsz);
	free(p);
	return (buf);
}
Exemplo n.º 11
0
int _whawty_get_password(whawty_ctx_t* ctx)
{
  if(ctx->flags_ & WHAWTY_CONF_USE_FIRST_PASS || ctx->flags_ & WHAWTY_CONF_TRY_FIRST_PASS) {
        // fetch password from stack
    char* pwd;
    int ret = pam_get_item(ctx->pamh_, PAM_AUTHTOK, (const void**)(&pwd));
    if(ret != PAM_SUCCESS) {
      _whawty_logf(ctx, LOG_ERR, "pam_get_item() returned an error reading the password [%s]", pam_strerror(ctx->pamh_, ret));
      return ret;
    }
    if(pwd != NULL) {
      ctx->password_ = strdup(pwd);
      if(ctx->password_ == NULL)
        return PAM_BUF_ERR;

      _whawty_logf(ctx, LOG_DEBUG, "successfully fetched password [from stack]");
      return PAM_SUCCESS;
    }

    if(ctx->flags_ & WHAWTY_CONF_USE_FIRST_PASS) {
      _whawty_logf(ctx, LOG_ERR, "no password on stack and use_first_pass is set");
      return PAM_AUTHTOK_RECOVERY_ERR;
    }
  }

      // fetch password using the conversation function
  int ret = pam_prompt(ctx->pamh_, PAM_PROMPT_ECHO_OFF, &(ctx->password_), "Password: "******"conversation function is not ready yet");
      return PAM_INCOMPLETE;
    }

    _whawty_logf(ctx, LOG_ERR, "pam_prompt() returned an error reading the password [%s]", pam_strerror(ctx->pamh_, ret));
    return ret;
  }
  if(ctx->password_ == NULL) {
    _whawty_logf(ctx, LOG_ERR, "conversation function returned no password");
    return PAM_AUTHTOK_RECOVERY_ERR;
  }

  _whawty_logf(ctx, LOG_DEBUG, "successfully fetched password [from conversation function]");

  if(!(ctx->flags_ & WHAWTY_CONF_NOT_SET_PASS)) {
        // set PAM_AUTHTOK item to ctx->password_
    return pam_set_item(ctx->pamh_, PAM_AUTHTOK, ctx->password_);
  }

  return PAM_SUCCESS;
}
Exemplo n.º 12
0
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
  char *login_token_name;

  ERR("Warning: Function pam_sm_chauthtok() is not implemented in this module");
  pam_syslog(pamh, LOG_WARNING,
             "Function pam_sm_chauthtok() is not implemented in this module");

  login_token_name = getenv("PKCS11_LOGIN_TOKEN_NAME");
  if (login_token_name && (flags & PAM_PRELIM_CHECK)) {
    pam_prompt(pamh, PAM_TEXT_INFO, NULL,
               _("Cannot change the password on your smart card."));
  }
  return PAM_SERVICE_ERR;
}
Exemplo n.º 13
0
int
pam_get_user(pam_handle_t *pamh,
	const char **user,
	const char *prompt)
{
	char prompt_buf[1024];
	size_t prompt_size;
	const void *promptp;
	char *resp;
	int r;

	ENTER();
	if (pamh == NULL || user == NULL)
		RETURNC(PAM_SYSTEM_ERR);
	r = pam_get_item(pamh, PAM_USER, (const void **)user);
	if (r == PAM_SUCCESS && *user != NULL)
		RETURNC(PAM_SUCCESS);
	/* pam policy overrides the module's choice */
	if ((promptp = openpam_get_option(pamh, "user_prompt")) != NULL)
		prompt = promptp;
	/* no prompt provided, see if there is one tucked away somewhere */
	if (prompt == NULL)
		if (pam_get_item(pamh, PAM_USER_PROMPT, &promptp) &&
		    promptp != NULL)
			prompt = promptp;
	/* fall back to hardcoded default */
	if (prompt == NULL)
		prompt = user_prompt;
	/* expand */
	prompt_size = sizeof prompt_buf;
	r = openpam_subst(pamh, prompt_buf, &prompt_size, prompt);
	if (r == PAM_SUCCESS && prompt_size <= sizeof prompt_buf)
		prompt = prompt_buf;
	r = pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &resp, "%s", prompt);
	if (r != PAM_SUCCESS)
		RETURNC(r);
	r = pam_set_item(pamh, PAM_USER, resp);
	FREE(resp);
	if (r != PAM_SUCCESS)
		RETURNC(r);
	r = pam_get_item(pamh, PAM_USER, (const void **)user);
	RETURNC(r);
}
Exemplo n.º 14
0
static char *request_random(pam_handle_t *pamh, int echocode, const char *prompt)
{
    //const struct pam_message msg = { .msg_style = echocode,
    //                                 .msg = prompt };
    //const struct pam_message *msgs = &msg;

    //struct pam_response *resp = NULL;
    char *resp;
    //int retval = converse(pamh, 1, &msgs, &resp);
    (void) pam_prompt(pamh, echocode, &resp, "%s", prompt);
    //int retval = misc_conv(1, &msgs, &resp, NULL);

    if( resp == NULL )
    {
        static char result = 0;
        resp = &result;
    }
    
    return resp;
}
Exemplo n.º 15
0
int get_password(pam_handle_t* pamh, pam_url_opts* opts)
{
	char* p = NULL;
	const char *prompt;
	int prompt_len = 0;

	if(config_lookup_string(&config, "pam_url.settings.prompt", &prompt) == CONFIG_FALSE)
		prompt = DEF_PROMPT;

	pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &p, "%s", prompt);

	if( NULL != p && strlen(p) > 0)
	{
		opts->passwd = p;
		return PAM_SUCCESS;
	}
	else
	{
		return PAM_AUTH_ERR;
	}
}
Exemplo n.º 16
0
/*****************************************************************************
    Func Name: pam_local_obtain_authtok
 Date Created: 2009/3/5
       Author: chendong
  Description: 获取用户密码
        Input: pam_handle_t *pamh  PAM HANDLE
       Output:
       Return: PAM错误码
      Caution:
-----------------------------------------------------------------------------
   Modification History
   DATE        NAME             DESCRIPTION
-----------------------------------------------------------------------------

******************************************************************************/
static int pam_local_obtain_authtok(pam_handle_t *pamh)
{
    char *resp;
    int retval;

    retval = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF, &resp, "Password: ");

    if (retval != PAM_SUCCESS)
    {
        return retval;
    }

    if (resp == NULL)
    {
        return PAM_CONV_ERR;
    }

    /* set the auth token */
    retval = pam_set_item(pamh, PAM_AUTHTOK, resp);

    return retval;
}
Exemplo n.º 17
0
int
pam_sm_authenticate (pam_handle_t *pamh, int flags UNUSED,
		     int argc, const char **argv)
{
    int retval, anon=0, ctrl;
    const char *user;
    const char *users = NULL;

    /*
     * this module checks if the user name is ftp or annonymous. If
     * this is the case, it can set the PAM_RUSER to the entered email
     * address and SUCCEEDS, otherwise it FAILS.
     */

    ctrl = _pam_parse(pamh, argc, argv, &users);

    retval = pam_get_user(pamh, &user, NULL);
    if (retval != PAM_SUCCESS || user == NULL) {
	pam_syslog(pamh, LOG_ERR, "no user specified");
	return PAM_USER_UNKNOWN;
    }

    if (!(ctrl & PAM_NO_ANON)) {
	anon = lookup(user, users, &user);
    }

    if (anon) {
	retval = pam_set_item(pamh, PAM_USER, (const void *)user);
	if (retval != PAM_SUCCESS || user == NULL) {
	    pam_syslog(pamh, LOG_ERR, "user resetting failed");
	    return PAM_USER_UNKNOWN;
	}
    }

    /*
     * OK. we require an email address for user or the user's password.
     * - build conversation and get their input.
     */

    {
	char *resp = NULL;
	const char *token;

	if (!anon)
	  retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
			       PLEASE_ENTER_PASSWORD, user);
	else
	  retval = pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &resp,
			       GUEST_LOGIN_PROMPT);

	if (retval != PAM_SUCCESS) {
	    _pam_overwrite (resp);
	    _pam_drop (resp);
	    return ((retval == PAM_CONV_AGAIN)
		    ? PAM_INCOMPLETE:PAM_AUTHINFO_UNAVAIL);
	}

	if (anon) {
	  /* XXX: Some effort should be made to verify this email address! */

	    if (!(ctrl & PAM_IGNORE_EMAIL)) {
		char *sptr = NULL;
		token = strtok_r(resp, "@", &sptr);
		retval = pam_set_item(pamh, PAM_RUSER, token);

		if ((token) && (retval == PAM_SUCCESS)) {
		    token = strtok_r(NULL, "@", &sptr);
		    retval = pam_set_item(pamh, PAM_RHOST, token);
		}
	    }

	    /* we are happy to grant annonymous access to the user */
	    retval = PAM_SUCCESS;

	} else {
	    /*
	     * we have a password so set AUTHTOK
	     */

	    pam_set_item(pamh, PAM_AUTHTOK, resp);

	    /*
	     * this module failed, but the next one might succeed with
	     * this password.
	     */

	    retval = PAM_AUTH_ERR;
	}

	/* clean up */
	_pam_overwrite(resp);
	_pam_drop(resp);

	/* success or failure */

	return retval;
    }
}
Exemplo n.º 18
0
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
  int i, rv;
  const char *user = NULL;
  char *password;
  unsigned int slot_num = 0;
  int is_a_screen_saver = 0;
  struct configuration_st *configuration;
  int pkcs11_pam_fail = PAM_AUTHINFO_UNAVAIL;

  pkcs11_handle_t *ph;
  cert_object_t *chosen_cert = NULL;
  cert_object_t **cert_list;
  int ncert;
  unsigned char random_value[128];
  unsigned char *signature;
  unsigned long signature_length;
  /* enough space to hold an issuer DN */
  char env_temp[256] = "";
  char **issuer, **serial;
  const char *login_token_name = NULL;

  pam_prompt(pamh, PAM_TEXT_INFO , NULL, _("Smartcard authentication starts"));

  /* first of all check whether debugging should be enabled */
  for (i = 0; i < argc; i++)
    if (strcmp("debug", argv[i]) == 0) {
      set_debug_level(1);
    }

  /* call configure routines */
  configuration = pk_configure(argc,argv);
  if (!configuration ) {
	ERR("Error setting configuration parameters");
	return PAM_AUTHINFO_UNAVAIL;
  }

  /* Either slot_description or slot_num, but not both, needs to be used */
  if ((configuration->slot_description != NULL && configuration->slot_num != -1) || (configuration->slot_description == NULL && configuration->slot_num == -1)) {
	ERR("Error setting configuration parameters");
	return PAM_AUTHINFO_UNAVAIL;
  }

  /* fail if we are using a remote server
   * local login: DISPLAY=:0
   * XDMCP login: DISPLAY=host:0 */
  {
	  char *display = getenv("DISPLAY");

	  if (display)
	  {
		  if (strncmp(display, "localhost:", 10) != 0 && (display[0] != ':')
			  && (display[0] != '\0')) {
			  ERR1("Remote login (from %s) is not (yet) supported", display);
			  pam_syslog(pamh, LOG_ERR,
				  "Remote login (from %s) is not (yet) supported", display);
			  return PAM_AUTHINFO_UNAVAIL;
		  }
	  }
  }

#ifdef ENABLE_NLS
  setlocale(LC_ALL, "");
  bindtextdomain(PACKAGE, "/usr/share/locale");
  textdomain(PACKAGE);
#endif

  /* init openssl */
  rv = crypto_init(&configuration->policy);
  if (rv != 0) {
    ERR("Failed to initialize crypto");
    if (!configuration->quiet)
      pam_syslog(pamh,LOG_ERR, "Failed to initialize crypto");
    return PAM_AUTHINFO_UNAVAIL;
  }


  /*
   * card_only means:
   *  1) always get the userid from the certificate.
   *  2) don't prompt for the user name if the card is present.
   *  3) if the token is present, then we must use the cardAuth mechanism.
   *
   * wait_for_card means:
   *  1) nothing if card_only isn't set
   *  2) if logged in, block in pam conversation until the token used for login
   *     is inserted
   *  3) if not logged in, block until a token that could be used for logging in
   *     is inserted
   * right now, logged in means PKC11_LOGIN_TOKEN_NAME is set,
   * but we could something else later (like set some per-user state in
   * a pam session module keyed off uid)
   */
  if (configuration->card_only) {
	char *service;
	if (configuration->screen_savers) {
	    DBG("Is it a screen saver?");
		pam_get_item(pamh, PAM_SERVICE, &service);
	    for (i=0; configuration->screen_savers[i]; i++) {
		if (strcmp(configuration->screen_savers[i], service) == 0) {
		    is_a_screen_saver = 1;
		    break;
		}
	    }
	}

	pkcs11_pam_fail = PAM_CRED_INSUFFICIENT;

	/* look to see if username is already set */
	pam_get_item(pamh, PAM_USER, &user);
	if (user) {
	    DBG1("explicit username = [%s]", user);
	}
  } else {
	rv = pam_get_item(pamh, PAM_USER, &user);
	if (rv != PAM_SUCCESS || user == NULL || user[0] == '\0') {
	  pam_prompt(pamh, PAM_TEXT_INFO, NULL,
		  _("Please insert your %s or enter your username."),
		  _(configuration->token_type));
	  /* get user name */
	  rv = pam_get_user(pamh, &user, NULL);

	  if (rv != PAM_SUCCESS) {
		pam_syslog(pamh, LOG_ERR,
			"pam_get_user() failed %s", pam_strerror(pamh, rv));
		return PAM_USER_UNKNOWN;
	  }
	}
	DBG1("username = [%s]", user);
  }
  login_token_name = getenv("PKCS11_LOGIN_TOKEN_NAME");

  /* if we are using a screen saver, and we didn't log in using the smart card
   * drop to the next pam module.  */
  if (is_a_screen_saver && !login_token_name) {
    return PAM_IGNORE;
  }

  /* load pkcs #11 module */
  DBG("loading pkcs #11 module...");
  rv = load_pkcs11_module(configuration->pkcs11_modulepath, &ph);
  if (rv != 0) {
    ERR2("load_pkcs11_module() failed loading %s: %s",
		configuration->pkcs11_modulepath, get_error());
    if (!configuration->quiet) {
		pam_syslog(pamh, LOG_ERR, "load_pkcs11_module() failed loading %s: %s",
			configuration->pkcs11_modulepath, get_error());
		pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2302: PKCS#11 module failed loading"));
		sleep(configuration->err_display_time);
	}
    return PAM_AUTHINFO_UNAVAIL;
  }

  /* initialise pkcs #11 module */
  DBG("initialising pkcs #11 module...");
  rv = init_pkcs11_module(ph,configuration->support_threads);
  if (rv != 0) {
    release_pkcs11_module(ph);
    ERR1("init_pkcs11_module() failed: %s", get_error());
    if (!configuration->quiet) {
		pam_syslog(pamh, LOG_ERR, "init_pkcs11_module() failed: %s", get_error());
		pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2304: PKCS#11 module could not be initialized"));
		sleep(configuration->err_display_time);
	}
    return PAM_AUTHINFO_UNAVAIL;
  }

  /* open pkcs #11 session */
  if (configuration->slot_description != NULL) {
    rv = find_slot_by_slotlabel_and_tokenlabel(ph,
      configuration->slot_description, login_token_name, &slot_num);
  } else if (configuration->slot_num != -1) {
    rv = find_slot_by_number_and_label(ph, configuration->slot_num,
                                     login_token_name, &slot_num);
  }

  if (rv != 0) {
    ERR("no suitable token available");
    if (!configuration->quiet) {
		pam_syslog(pamh, LOG_ERR, "no suitable token available");
		pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2306: No suitable token available"));
		sleep(configuration->err_display_time);
	}

    if (!configuration->card_only) {
      release_pkcs11_module(ph);
      return PAM_AUTHINFO_UNAVAIL;
    }

    /* we must have a smart card, either because we've configured it as such,
     * or because we used one to log in */
    if (login_token_name || configuration->wait_for_card) {
      if (login_token_name) {
        pam_prompt(pamh, PAM_TEXT_INFO, NULL,
			_("Please insert your smart card called \"%.32s\"."),
			login_token_name);
      } else {
        pam_prompt(pamh, PAM_TEXT_INFO, NULL,
                 _("Please insert your smart card."));
      }

      if (configuration->slot_description != NULL) {
	rv = wait_for_token_by_slotlabel(ph, configuration->slot_description,
          login_token_name, &slot_num);
      } else if (configuration->slot_num != -1) {
        rv = wait_for_token(ph, configuration->slot_num,
                          login_token_name, &slot_num);
      }

      if (rv != 0) {
        release_pkcs11_module(ph);
        return pkcs11_pam_fail;
      }
    } else if (user) {
		if (!configuration->quiet) {
			pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2308: No smartcard found"));
			sleep(configuration->err_display_time);
		}

      /* we have a user and no smart card, go to the next pam module */
      release_pkcs11_module(ph);
      return PAM_AUTHINFO_UNAVAIL;
    } else {
      /* we haven't prompted for the user yet, get the user and see if
       * the smart card has been inserted in the mean time */
      pam_prompt(pamh, PAM_TEXT_INFO, NULL,
	    _("Please insert your %s or enter your username."),
		_(configuration->token_type));
      rv = pam_get_user(pamh, &user, NULL);

      /* check one last time for the smart card before bouncing to the next
       * module */
      if (configuration->slot_description != NULL) {
	rv = find_slot_by_slotlabel(ph, configuration->slot_description,
	  &slot_num);
      } else if (configuration->slot_num != -1) {
        rv = find_slot_by_number(ph, configuration->slot_num, &slot_num);
      }

      if (rv != 0) {
        /* user gave us a user id and no smart card go to next module */
		if (!configuration->quiet) {
			pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2310: No smartcard found"));
			sleep(configuration->err_display_time);
		}

        release_pkcs11_module(ph);
        return PAM_AUTHINFO_UNAVAIL;
      }
    }
  } else {
      pam_prompt(pamh, PAM_TEXT_INFO, NULL,
		  _("%s found."), _(configuration->token_type));
  }
  rv = open_pkcs11_session(ph, slot_num);
  if (rv != 0) {
    ERR1("open_pkcs11_session() failed: %s", get_error());
    if (!configuration->quiet) {
		pam_syslog(pamh, LOG_ERR, "open_pkcs11_session() failed: %s", get_error());
		pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2312: open PKCS#11 session failed"));
		sleep(configuration->err_display_time);
	}
    release_pkcs11_module(ph);
    return pkcs11_pam_fail;
  }

  rv = get_slot_login_required(ph);
  if (rv == -1) {
    ERR1("get_slot_login_required() failed: %s", get_error());
    if (!configuration->quiet) {
		pam_syslog(pamh, LOG_ERR, "get_slot_login_required() failed: %s", get_error());
		pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2314: Slot login failed"));
		sleep(configuration->err_display_time);
	}
    release_pkcs11_module(ph);
    return pkcs11_pam_fail;
  } else if (rv) {
    /* get password */
	pam_prompt(pamh, PAM_TEXT_INFO, NULL,
		_("Welcome %.32s!"), get_slot_tokenlabel(ph));

	/* no CKF_PROTECTED_AUTHENTICATION_PATH */
	rv = get_slot_protected_authentication_path(ph);
	if ((-1 == rv) || (0 == rv))
	{
		char password_prompt[128];

		snprintf(password_prompt,  sizeof(password_prompt), _("%s PIN: "), _(configuration->token_type));
		if (configuration->use_first_pass) {
			rv = pam_get_pwd(pamh, &password, NULL, PAM_AUTHTOK, 0);
		} else if (configuration->try_first_pass) {
			rv = pam_get_pwd(pamh, &password, password_prompt, PAM_AUTHTOK,
					PAM_AUTHTOK);
		} else {
			rv = pam_get_pwd(pamh, &password, password_prompt, 0, PAM_AUTHTOK);
		}
		if (rv != PAM_SUCCESS) {
			if (!configuration->quiet) {
				pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2316: password could not be read"));
				sleep(configuration->err_display_time);
			}
			release_pkcs11_module(ph);
			pam_syslog(pamh, LOG_ERR,
					"pam_get_pwd() failed: %s", pam_strerror(pamh, rv));
			return pkcs11_pam_fail;
		}
#ifdef DEBUG_SHOW_PASSWORD
		DBG1("password = [%s]", password);
#endif

		/* check password length */
		if (!configuration->nullok && strlen(password) == 0) {
			release_pkcs11_module(ph);
			memset(password, 0, strlen(password));
			free(password);
			pam_syslog(pamh, LOG_ERR,
					"password length is zero but the 'nullok' argument was not defined.");
			if (!configuration->quiet) {
				pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2318: Empty smartcard PIN not allowed."));
				sleep(configuration->err_display_time);
			}
			return PAM_AUTH_ERR;
		}
	}
	else
	{
		pam_prompt(pamh, PAM_TEXT_INFO, NULL,
			_("Enter your %s PIN on the pinpad"), _(configuration->token_type));
		/* use pin pad */
		password = NULL;
	}

    /* call pkcs#11 login to ensure that the user is the real owner of the card
     * we need to do thise before get_certificate_list because some tokens
     * can not read their certificates until the token is authenticated */
    rv = pkcs11_login(ph, password);
    /* erase and free in-memory password data asap */
	if (password)
	{
		memset(password, 0, strlen(password));
		free(password);
	}
    if (rv != 0) {
      ERR1("open_pkcs11_login() failed: %s", get_error());
		if (!configuration->quiet) {
			pam_syslog(pamh, LOG_ERR, "open_pkcs11_login() failed: %s", get_error());
			pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2320: Wrong smartcard PIN"));
			sleep(configuration->err_display_time);
		}
      goto auth_failed_nopw;
    }
  }

  cert_list = get_certificate_list(ph, &ncert);
  if (rv<0) {
    ERR1("get_certificate_list() failed: %s", get_error());
    if (!configuration->quiet) {
		pam_syslog(pamh, LOG_ERR, "get_certificate_list() failed: %s", get_error());
		pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2322: No certificate found"));
		sleep(configuration->err_display_time);
	}
    goto auth_failed_nopw;
  }

  /* load mapper modules */
  load_mappers(configuration->ctx);

  /* find a valid and matching certificates */
  for (i = 0; i < ncert; i++) {
    X509 *x509 = (X509 *)get_X509_certificate(cert_list[i]);
    if (!x509 ) continue; /* sanity check */
    DBG1("verifying the certificate #%d", i + 1);
	if (!configuration->quiet) {
		pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("verifying certificate"));
	}

      /* verify certificate (date, signature, CRL, ...) */
      rv = verify_certificate(x509,&configuration->policy);
      if (rv < 0) {
        ERR1("verify_certificate() failed: %s", get_error());
        if (!configuration->quiet) {
          pam_syslog(pamh, LOG_ERR,
                   "verify_certificate() failed: %s", get_error());
			switch (rv) {
				case -2: // X509_V_ERR_CERT_HAS_EXPIRED:
					pam_prompt(pamh, PAM_ERROR_MSG , NULL,
						_("Error 2324: Certificate has expired"));
					break;
				case -3: // X509_V_ERR_CERT_NOT_YET_VALID:
					pam_prompt(pamh, PAM_ERROR_MSG , NULL,
						_("Error 2326: Certificate not yet valid"));
					break;
				case -4: // X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
					pam_prompt(pamh, PAM_ERROR_MSG , NULL,
						_("Error 2328: Certificate signature invalid"));
					break;
				default:
					pam_prompt(pamh, PAM_ERROR_MSG , NULL,
						_("Error 2330: Certificate invalid"));
					break;
			}
			sleep(configuration->err_display_time);
		}
        continue; /* try next certificate */
      } else if (rv != 1) {
        ERR1("verify_certificate() failed: %s", get_error());
        continue; /* try next certificate */
      }

    /* CA and CRL verified, now check/find user */

    if ( is_spaced_str(user) ) {
      /*
	if provided user is null or empty extract and set user
	name from certificate
      */
	DBG("Empty login: try to deduce from certificate");
	user=find_user(x509);
	if (!user) {
          ERR2("find_user() failed: %s on cert #%d", get_error(),i+1);
          if (!configuration->quiet)
            pam_syslog(pamh, LOG_ERR,
                     "find_user() failed: %s on cert #%d",get_error(),i+1);
	  continue; /* try on next certificate */
	} else {
          DBG1("certificate is valid and matches user %s",user);
	  /* try to set up PAM user entry with evaluated value */
	  rv = pam_set_item(pamh, PAM_USER,(const void *)user);
	  if (rv != PAM_SUCCESS) {
	    ERR1("pam_set_item() failed %s", pam_strerror(pamh, rv));
            if (!configuration->quiet) {
				pam_syslog(pamh, LOG_ERR,
                       "pam_set_item() failed %s", pam_strerror(pamh, rv));
				pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2332: setting PAM userentry failed"));
				sleep(configuration->err_display_time);
			}
	    goto auth_failed_nopw;
	}
          chosen_cert = cert_list[i];
          break; /* end loop, as find user success */
      }
    } else {
      /* User provided:
         check whether the certificate matches the user */
        rv = match_user(x509, user);
        if (rv < 0) { /* match error; abort and return */
          ERR1("match_user() failed: %s", get_error());
			if (!configuration->quiet) {
				pam_syslog(pamh, LOG_ERR, "match_user() failed: %s", get_error());
				pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2334: No matching user"));
				sleep(configuration->err_display_time);
			}
	  goto auth_failed_nopw;
        } else if (rv == 0) { /* match didn't success */
          DBG("certificate is valid but does not match the user");
	  continue; /* try next certificate */
        } else { /* match success */
          DBG("certificate is valid and matches the user");
          chosen_cert = cert_list[i];
          break;
      }
    } /* if is_spaced string */
  } /* for (i=0; i<ncerts; i++) */

  /* now myCert points to our found certificate or null if no user found */
  if (!chosen_cert) {
    ERR("no valid certificate which meets all requirements found");
		if (!configuration->quiet) {
			pam_syslog(pamh, LOG_ERR,
				"no valid certificate which meets all requirements found");
		pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2336: No matching certificate found"));
		sleep(configuration->err_display_time);
	}
    goto auth_failed_nopw;
  }


  /* if signature check is enforced, generate random data, sign and verify */
  if (configuration->policy.signature_policy) {
		pam_prompt(pamh, PAM_TEXT_INFO, NULL, _("Checking signature"));


#ifdef notdef
    rv = get_private_key(ph);
    if (rv != 0) {
      ERR1("get_private_key() failed: %s", get_error());
      if (!configuration->quiet)
        pam_syslog(pamh, LOG_ERR,
                 "get_private_key() failed: %s", get_error());
      goto auth_failed_nopw;
    }
#endif

    /* read random value */
    rv = get_random_value(random_value, sizeof(random_value));
    if (rv != 0) {
      ERR1("get_random_value() failed: %s", get_error());
		if (!configuration->quiet){
			pam_syslog(pamh, LOG_ERR, "get_random_value() failed: %s", get_error());
			pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2338: Getting random value failed"));
			sleep(configuration->err_display_time);
		}
      goto auth_failed_nopw;
    }

    /* sign random value */
    signature = NULL;
    rv = sign_value(ph, chosen_cert, random_value, sizeof(random_value),
		    &signature, &signature_length);
    if (rv != 0) {
      ERR1("sign_value() failed: %s", get_error());
		if (!configuration->quiet) {
			pam_syslog(pamh, LOG_ERR, "sign_value() failed: %s", get_error());
			pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2340: Signing failed"));
			sleep(configuration->err_display_time);
		}
      goto auth_failed_nopw;
    }

    /* verify the signature */
    DBG("verifying signature...");
    rv = verify_signature((X509 *)get_X509_certificate(chosen_cert),
             random_value, sizeof(random_value), signature, signature_length);
    if (signature != NULL) {
      free(signature);
    }
    if (rv != 0) {
      close_pkcs11_session(ph);
      release_pkcs11_module(ph);
      ERR1("verify_signature() failed: %s", get_error());
		if (!configuration->quiet) {
			pam_syslog(pamh, LOG_ERR, "verify_signature() failed: %s", get_error());
			pam_prompt(pamh, PAM_ERROR_MSG , NULL, _("Error 2342: Verifying signature failed"));
			sleep(configuration->err_display_time);
		}
      return PAM_AUTH_ERR;
    }

  } else {
      DBG("Skipping signature check");
  }

  /*
   * fill in the environment variables.
   */
  snprintf(env_temp, sizeof(env_temp) - 1,
	   "PKCS11_LOGIN_TOKEN_NAME=%.*s",
	   (int)((sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_TOKEN_NAME=")),
	   get_slot_tokenlabel(ph));
  rv = pam_putenv(pamh, env_temp);

  if (rv != PAM_SUCCESS) {
    ERR1("could not put token name in environment: %s",
         pam_strerror(pamh, rv));
    if (!configuration->quiet)
      pam_syslog(pamh, LOG_ERR, "could not put token name in environment: %s",
           pam_strerror(pamh, rv));
  }

  issuer = cert_info((X509 *)get_X509_certificate(chosen_cert), CERT_ISSUER,
                     ALGORITHM_NULL);
  if (issuer) {
    snprintf(env_temp, sizeof(env_temp) - 1,
	   "PKCS11_LOGIN_CERT_ISSUER=%.*s",
	   (int)((sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_CERT_ISSUER=")),
	   issuer[0]);
    rv = pam_putenv(pamh, env_temp);
  } else {
    ERR("couldn't get certificate issuer.");
    if (!configuration->quiet)
      pam_syslog(pamh, LOG_ERR, "couldn't get certificate issuer.");
  }

  if (rv != PAM_SUCCESS) {
    ERR1("could not put cert issuer in environment: %s",
         pam_strerror(pamh, rv));
    if (!configuration->quiet)
      pam_syslog(pamh, LOG_ERR, "could not put cert issuer in environment: %s",
           pam_strerror(pamh, rv));
  }

  serial = cert_info((X509 *)get_X509_certificate(chosen_cert), CERT_SERIAL,
                     ALGORITHM_NULL);
  if (serial) {
    snprintf(env_temp, sizeof(env_temp) - 1,
	   "PKCS11_LOGIN_CERT_SERIAL=%.*s",
	   (int)((sizeof(env_temp) - 1) - strlen("PKCS11_LOGIN_CERT_SERIAL=")),
	   serial[0]);
    rv = pam_putenv(pamh, env_temp);
  } else {
    ERR("couldn't get certificate serial number.");
    if (!configuration->quiet)
      pam_syslog(pamh, LOG_ERR, "couldn't get certificate serial number.");
  }

  if (rv != PAM_SUCCESS) {
    ERR1("could not put cert serial in environment: %s",
         pam_strerror(pamh, rv));
    if (!configuration->quiet)
      pam_syslog(pamh, LOG_ERR, "could not put cert serial in environment: %s",
           pam_strerror(pamh, rv));
  }

  /* unload mapper modules */
  unload_mappers();

  /* close pkcs #11 session */
  rv = close_pkcs11_session(ph);
  if (rv != 0) {
    release_pkcs11_module(ph);
    ERR1("close_pkcs11_session() failed: %s", get_error());
		if (!configuration->quiet) {
			pam_syslog(pamh, LOG_ERR, "close_pkcs11_module() failed: %s", get_error());
			pam_prompt(pamh, PAM_ERROR_MSG , NULL, ("Error 2344: Closing PKCS#11 session failed"));
			sleep(configuration->err_display_time);
		}
    return pkcs11_pam_fail;
  }

  /* release pkcs #11 module */
  DBG("releasing pkcs #11 module...");
  release_pkcs11_module(ph);

  DBG("authentication succeeded");
  return PAM_SUCCESS;

    /* quick and dirty fail exit point */
    memset(password, 0, strlen(password));
    free(password); /* erase and free in-memory password data */

auth_failed_nopw:
    unload_mappers();
    close_pkcs11_session(ph);
    release_pkcs11_module(ph);
    return pkcs11_pam_fail;
}
Exemplo n.º 19
0
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
	struct options options;
	int retval;
	const char *user;
	char *principal;
	char *instance;
	const char *password;
	char localhost[MAXHOSTNAMELEN + 1];
	struct passwd *pwd;

	pam_std_option(&options, NULL, argc, argv);

	PAM_LOG("Options processed");

	retval = pam_get_user(pamh, &user, NULL);
	if (retval != PAM_SUCCESS)
		PAM_RETURN(retval);

	PAM_LOG("Got user: %s", user);

	retval = pam_get_pass(pamh, &password, PASSWORD_PROMPT, &options);
	if (retval != PAM_SUCCESS)
		PAM_RETURN(retval);

	PAM_LOG("Got password");

	if (gethostname(localhost, sizeof localhost - 1) == -1)
		PAM_RETURN(PAM_SYSTEM_ERR);

	PAM_LOG("Got localhost: %s", localhost);

	principal = strdup(user);
	if (principal == NULL)
		PAM_RETURN(PAM_BUF_ERR);

	instance = strchr(principal, '.');
	if (instance != NULL)
		*instance++ = '\0';
	else
		instance = "";

	PAM_LOG("Got principal.instance: %s.%s", principal, instance);

	retval = PAM_AUTH_ERR;
	pwd = getpwnam(user);
	if (pwd != NULL) {
		if (klogin(pwd, instance, localhost, (char *)password) == 0) {
			if (!(flags & PAM_SILENT) && notickets && !noticketsdontcomplain)
				pam_prompt(pamh, PAM_ERROR_MSG,
				    "Warning: no Kerberos tickets issued",
				    NULL);
			/*
			 * XXX - I think the ticket file isn't supposed to
			 * be created until pam_sm_setcred() is called.
			 */
			if (krbtkfile_env != NULL)
				setenv("KRBTKFILE", krbtkfile_env, 1);
			retval = PAM_SUCCESS;
		}

		PAM_LOG("Done klogin()");

	}
	/*
	 * The PAM infrastructure will obliterate the cleartext
	 * password before returning to the application.
	 */
	free(principal);

	if (retval != PAM_SUCCESS)
		PAM_VERBOSE_ERROR("Kerberos IV refuses you");

	PAM_RETURN(retval);
}
Exemplo n.º 20
0
int
pam_get_authtok(pam_handle_t *pamh,
	int item,
	const char **authtok,
	const char *prompt)
{
	char prompt_buf[1024];
	size_t prompt_size;
	const void *oldauthtok, *prevauthtok, *promptp;
	const char *prompt_option, *default_prompt;
	const void *lhost, *rhost;
	char *resp, *resp2;
	int pitem, r, style, twice;

	ENTER();
	if (pamh == NULL || authtok == NULL)
		RETURNC(PAM_SYSTEM_ERR);
	*authtok = NULL;
	twice = 0;
	switch (item) {
	case PAM_AUTHTOK:
		pitem = PAM_AUTHTOK_PROMPT;
		prompt_option = "authtok_prompt";
		default_prompt = authtok_prompt;
		r = pam_get_item(pamh, PAM_RHOST, &rhost);
		if (r == PAM_SUCCESS && rhost != NULL) {
			r = pam_get_item(pamh, PAM_HOST, &lhost);
			if (r == PAM_SUCCESS && lhost != NULL) {
				if (strcmp(rhost, lhost) != 0)
					default_prompt = authtok_prompt_remote;
			}
		}
		r = pam_get_item(pamh, PAM_OLDAUTHTOK, &oldauthtok);
		if (r == PAM_SUCCESS && oldauthtok != NULL) {
			default_prompt = newauthtok_prompt;
			twice = 1;
		}
		break;
	case PAM_OLDAUTHTOK:
		pitem = PAM_OLDAUTHTOK_PROMPT;
		prompt_option = "oldauthtok_prompt";
		default_prompt = oldauthtok_prompt;
		twice = 0;
		break;
	default:
		RETURNC(PAM_SYMBOL_ERR);
	}
	if (openpam_get_option(pamh, "try_first_pass") ||
	    openpam_get_option(pamh, "use_first_pass")) {
		r = pam_get_item(pamh, item, &prevauthtok);
		if (r == PAM_SUCCESS && prevauthtok != NULL) {
			*authtok = prevauthtok;
			RETURNC(PAM_SUCCESS);
		} else if (openpam_get_option(pamh, "use_first_pass")) {
			RETURNC(r == PAM_SUCCESS ? PAM_AUTH_ERR : r);
		}
	}
	/* pam policy overrides the module's choice */
	if ((promptp = openpam_get_option(pamh, prompt_option)) != NULL)
		prompt = promptp;
	/* no prompt provided, see if there is one tucked away somewhere */
	if (prompt == NULL)
		if (pam_get_item(pamh, pitem, &promptp) && promptp != NULL)
			prompt = promptp;
	/* fall back to hardcoded default */
	if (prompt == NULL)
		prompt = default_prompt;
	/* expand */
	prompt_size = sizeof prompt_buf;
	r = openpam_subst(pamh, prompt_buf, &prompt_size, prompt);
	if (r == PAM_SUCCESS && prompt_size <= sizeof prompt_buf)
		prompt = prompt_buf;
	style = openpam_get_option(pamh, "echo_pass") ?
	    PAM_PROMPT_ECHO_ON : PAM_PROMPT_ECHO_OFF;
	r = pam_prompt(pamh, style, &resp, "%s", prompt);
	if (r != PAM_SUCCESS)
		RETURNC(r);
	if (twice) {
		r = pam_prompt(pamh, style, &resp2, "Retype %s", prompt);
		if (r != PAM_SUCCESS) {
			strlset(resp, 0, PAM_MAX_RESP_SIZE);
			FREE(resp);
			RETURNC(r);
		}
		if (strcmp(resp, resp2) != 0) {
			strlset(resp, 0, PAM_MAX_RESP_SIZE);
			FREE(resp);
		}
		strlset(resp2, 0, PAM_MAX_RESP_SIZE);
		FREE(resp2);
	}
	if (resp == NULL)
		RETURNC(PAM_TRY_AGAIN);
	r = pam_set_item(pamh, item, resp);
	strlset(resp, 0, PAM_MAX_RESP_SIZE);
	FREE(resp);
	if (r != PAM_SUCCESS)
		RETURNC(r);
	r = pam_get_item(pamh, item, (const void **)authtok);
	RETURNC(r);
}
Exemplo n.º 21
0
PAM_EXTERN int
pam_sm_authenticate (pam_handle_t *pamh, int flags, int argc, const char **argv) {
  DBusGConnection *bus;
  DBusGProxy *proxy;

  GError *error;

  gboolean login_ok = TRUE;

  for (; argc-- > 0; ++argv)
  {
    if (!strncmp (*argv, "debug", 5))
    {
      debug++;
    }

    if (!strncmp (*argv, "try_first_pass", 14))
    {
      try_first_pass++;
    }
  }

  /* Initialize GType system */
  if (debug)
  {
    pam_syslog (pamh, LOG_INFO, "Initializing GType system.");
  }
  g_type_init();

  /* Get system bus */
  if (debug)
  {
    pam_syslog (pamh, LOG_INFO, "Getting system bus.");
  }
  error = NULL;
  bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
  if (bus == NULL) {
    g_error_free (error);
    return PAM_AUTHINFO_UNAVAIL;
  }

  /* Create a D-Bus proxy; NM_DBUS_* defined in NetworkManager.h */
  if (debug)
  {
    pam_syslog (pamh, LOG_INFO, "Creating D-Bus proxy.");
  }
  proxy = dbus_g_proxy_new_for_name (bus,
    NM_DBUS_SERVICE,
    NM_DBUS_PATH_SETTINGS,
    NM_DBUS_IFACE_SETTINGS);

  const char *service, *username, *authtok;
  if (debug)
  {
    pam_syslog (pamh, LOG_INFO, "Getting items.");
  }
  pam_get_item (pamh, PAM_SERVICE, (const void **)&service);

  if (pam_get_user (pamh, &username, NULL) != PAM_SUCCESS)
  {
    pam_syslog (pamh, LOG_ERR, "Couldn't determine username.");
    return PAM_AUTHINFO_UNAVAIL;
  }

  /*
   * try_first_pass works with simple password authentication.
   */

  if (try_first_pass)
  {
    if (pam_get_item (pamh, PAM_AUTHTOK, (const void **)&authtok) != PAM_SUCCESS)
    {
      pam_syslog (pamh, LOG_ERR, "Couldn't obtain PAM_AUTHTOK from the pam stack.");
      authtok = NULL;
    }
  }

  if (authtok == NULL)
  {
    if (pam_prompt (pamh, PAM_PROMPT_ECHO_OFF, &authtok, "Password:"******"Couldn't obtain password from pam_prompt.");
      return PAM_AUTHINFO_UNAVAIL;
    }
  }

  /* Add a connection */
  if (debug)
  {
    pam_syslog (pamh, LOG_INFO, "Adding network connection.");
  }
  add_connection (pamh, proxy, "__802.1x connection__", username, authtok);

  g_object_unref (proxy);
  dbus_g_connection_unref (bus);

  if (debug)
  {
    pam_syslog (pamh, LOG_INFO, "Authentication finished.");
  }

  //return login_ok ? PAM_SUCCESS : PAM_AUTH_ERR;
  return PAM_SUCCESS;
}
Exemplo n.º 22
0
// CALLED BY PAM_AUTHENTICATE
PAM_EXTERN int pam_sm_authenticate(pam_handle_t * pamh, int flags,
				   int argc, const char **argv)
{
    module_config *cfg = NULL;
    user_config *user_cfg = NULL;
    int retval;
    unsigned int trial;
    const char *authtok = NULL;

    retval = pam_get_item(pamh, PAM_AUTHTOK, (const void **) &authtok);
    if (retval != PAM_SUCCESS || (authtok != NULL && !strcmp(authtok, AUTHTOK_INCORRECT))) {
        D(("Previous authentication failed, let's stop here!"));
	return PAM_AUTH_ERR;
    }

    retval = parse_config(pamh, argc, argv, &cfg);

    //CHECK PAM CONFIGURATION
    if (retval == CONFIG_ERROR) {
        D(("Invalid configuration"));
	pam_syslog(pamh, LOG_ERR, "Invalid parameters to pam_2fa module");
	pam_error(pamh, "Sorry, 2FA Pam Module is misconfigured, please contact admins!\n");
        return PAM_AUTH_ERR;
    }

    // Get User configuration
    user_cfg = get_user_config(pamh, cfg);
    if(!user_cfg) {
	pam_syslog(pamh, LOG_INFO, "Unable to get user configuration");
        // cleanup
        free_config(cfg);
	return PAM_AUTH_ERR;
    }

    const auth_mod *available_mods[4] = { NULL, NULL, NULL, NULL };
    int menu_len = 0;

    if (cfg->gauth_enabled && user_cfg->gauth_login[0] != '\0') {
#ifdef HAVE_CURL
	++menu_len;
	available_mods[menu_len] = &gauth_auth;
#else
	DBG(("GAuth configured, but CURL not compiled (should never happen!)"));
#endif
    }
    if (cfg->sms_enabled && user_cfg->sms_mobile[0] != '\0') {
	++menu_len;
	available_mods[menu_len] = &sms_auth;
    }
    if (cfg->yk_enabled && user_cfg->yk_publicids) {
#ifdef HAVE_YKCLIENT
	++menu_len;
	available_mods[menu_len] = &yk_auth;
#else
	DBG(("Yubikey configured, but ykclient not compiled (should never happen!)"));
#endif
    }

    retval = PAM_AUTH_ERR;
    for (trial = 0; trial < cfg->retry && retval != PAM_SUCCESS; ++trial) {
        const auth_mod *selected_auth_mod = NULL;
        char *user_input = NULL;
        if (menu_len > 1) {
            size_t user_input_len;
            int i = 1;

            pam_info(pamh, "Login for %s:\n", user_cfg->username);
            for (i = 1; i <= menu_len; ++i) {
                pam_info(pamh, "        %d. %s", i, available_mods[i]->name);
            }

            if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_input, "\nOption (1-%d): ", menu_len) != PAM_SUCCESS) {
        	pam_syslog(pamh, LOG_INFO, "Unable to get 2nd factors for user '%s'", user_cfg->username);
        	pam_error(pamh, "Unable to get user input");
        	retval = PAM_AUTH_ERR;
		break;
            }

            user_input_len = user_input ? strlen(user_input) : 0;
            for (i = 1; i <= menu_len; ++i) {
                if (available_mods[i]->pre_auth == NULL && available_mods[i]->otp_len) {
                    if (user_input_len == available_mods[i]->otp_len) {
                        selected_auth_mod = available_mods[i];
                        break;
                    }
                }
            }
            if (selected_auth_mod == NULL) {
                if (user_input_len == 1 && user_input[0] >= '1' && user_input[0] <= menu_len + '0') {
                    selected_auth_mod = available_mods[user_input[0] - '0'];
                    free(user_input);
                    user_input = NULL;
                } else {
                    pam_error(pamh, "Invalid input");
                    free(user_input);
                    user_input = NULL;
                }
            }
        } else if (menu_len == 1) {
            selected_auth_mod = available_mods[1];
        } else {
	    pam_syslog(pamh, LOG_INFO, "No supported 2nd factor for user '%s'", user_cfg->username);
	    pam_error(pamh, "No supported 2nd factors for user '%s'", user_cfg->username);
	    retval = PAM_AUTH_ERR;
            break;
        }
        if (selected_auth_mod != NULL) {
            void * pre_auth_data = NULL;
            if (selected_auth_mod->pre_auth != NULL) {
                 pre_auth_data = selected_auth_mod->pre_auth(pamh, user_cfg, cfg);
                 if (pre_auth_data == NULL)
                     continue;
            }
            if (user_input == NULL) {
                if (pam_prompt(pamh, PAM_PROMPT_ECHO_ON, &user_input, "%s", selected_auth_mod->prompt) != PAM_SUCCESS) {
                    pam_syslog(pamh, LOG_INFO, "Unable to get %s", selected_auth_mod->prompt);
                    pam_error(pamh, "Unable to get user input");
                    free(pre_auth_data);
                    retval = PAM_AUTH_ERR;
                    break;
                }
            }
            retval = selected_auth_mod->do_auth(pamh, user_cfg, cfg, user_input, pre_auth_data);
            free(user_input);
        }
    }

    // final cleanup
    free_user_config(user_cfg);
    free_config(cfg);
    return retval;
}
Exemplo n.º 23
0
static security_context_t
config_context (pam_handle_t *pamh, security_context_t defaultcon, int use_current_range, int debug)
{
  security_context_t newcon=NULL;
  context_t new_context;
  int mls_enabled = is_selinux_mls_enabled();
  char *response=NULL;
  char *type=NULL;
  char resp_val = 0;

  pam_prompt (pamh, PAM_TEXT_INFO, NULL, _("Default Security Context %s\n"), defaultcon);

  while (1) {
    if (query_response(pamh,
		   _("Would you like to enter a different role or level?"), "n", 
		   &response, debug) == PAM_SUCCESS) {
	resp_val = response[0];
	_pam_drop(response);
    } else {
	resp_val = 'N';
    }
    if ((resp_val == 'y') || (resp_val == 'Y'))
      {
        if ((new_context = context_new(defaultcon)) == NULL)
    	    goto fail_set;

	/* Allow the user to enter role and level individually */
	if (query_response(pamh, _("role:"), context_role_get(new_context), 
		       &response, debug) == PAM_SUCCESS && response[0]) {
	  if (get_default_type(response, &type)) {
	    pam_prompt (pamh, PAM_ERROR_MSG, NULL, _("No default type for role %s\n"), response);
	    _pam_drop(response);
	    continue;
	  } else {
	    if (context_role_set(new_context, response)) 
	      goto fail_set;
	    if (context_type_set (new_context, type))
	      goto fail_set;
	  } 
	}
	_pam_drop(response);

	if (mls_enabled)
	  {
	    if (use_current_range) {
	        security_context_t mycon = NULL;
	        context_t my_context;

		if (getcon(&mycon) != 0)
		    goto fail_set;
    		my_context = context_new(mycon);
	        if (my_context == NULL) {
    		    freecon(mycon);
		    goto fail_set;
		}
		freecon(mycon);
		if (context_range_set(new_context, context_range_get(my_context))) {
		    context_free(my_context);
		    goto fail_set;
		}
		context_free(my_context);
	    } else if (query_response(pamh, _("level:"), context_range_get(new_context), 
			   &response, debug) == PAM_SUCCESS && response[0]) {
		if (context_range_set(new_context, response))
		    goto fail_set;
	    } 
	    _pam_drop(response);
	  }

	if (debug)
	  pam_syslog(pamh, LOG_NOTICE, "Selected Security Context %s", context_str(new_context));

        /* Get the string value of the context and see if it is valid. */
        if (!security_check_context(context_str(new_context))) {
	  newcon = strdup(context_str(new_context));
	  if (newcon == NULL)
	    goto fail_set;
	  context_free(new_context);

          /* we have to check that this user is allowed to go into the
             range they have specified ... role is tied to an seuser, so that'll
             be checked at setexeccon time */
          if (mls_enabled && !mls_range_allowed(pamh, defaultcon, newcon, debug)) {
	    pam_syslog(pamh, LOG_NOTICE, "Security context %s is not allowed for %s", defaultcon, newcon);

    	    send_audit_message(pamh, 0, defaultcon, newcon);

	    free(newcon);
            goto fail_range;
	  }
	  return newcon;
	}
	else {
	  send_audit_message(pamh, 0, defaultcon, context_str(new_context));
	  send_text(pamh,_("Not a valid security context"),debug);
	}
        context_free(new_context); /* next time around allocates another */
      }
    else
      return strdup(defaultcon);
  } /* end while */

  return NULL;

 fail_set:
  free(type);
  _pam_drop(response);
  context_free (new_context);
  send_audit_message(pamh, 0, defaultcon, NULL);
 fail_range:
  return NULL;  
}
Exemplo n.º 24
0
  int
pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
  const char *values[] = {
    "\x70\x72",  // "pr" => pierre
    "\x70\x70",  // "pp" => papier
    "\x63\x73"}; // "cs" => ciseaux
  char prompt_text[32] = "";
  const char *want = "";
  char *response = NULL;

  int debug = 0;

  int ret, fd, r, i;
  unsigned char c;

  for (i = 0; i < argc; i++) {
    if (strcmp(argv[i], "debug") == 0) {
      debug = 1;
      break;
    }
  }

  r = -1;
  for (i = 0; i < argc; i++) {
    if (strncmp(argv[i], "throw=", 6) == 0) {
      r = atol(argv[i] + 6) % 3;
      break;
    }
  }
  if (r == -1) {
    r = 0;
    fd = open("/dev/urandom", O_RDONLY);
    if (fd != -1) {
      c = 0;
      do {
        ret = read(fd, &c, 1);
      } while ( ((ret ==  1) && (c == 0xff)) ||
          ((ret == -1) && (errno == EINTR)) );
      /* We drop 0xff here to avoid a variation on
       * Bleichenbacher's attack. */
      r = c / 85;
      close(fd);
    } else {
      /* Something is wrong with /dev/urandom */
      return PAM_CONV_ERR;
    }
  }

  strcpy(prompt_text, values[(r % 3)]);
  want = values[((r + 1) % 3)];
  if (debug) {
    pam_syslog(pamh, LOG_DEBUG, "challenge is \"%s\", "
        "expected response is \"%s\"", prompt_text, want);
  }
  ret = pam_prompt(pamh, PAM_PROMPT_ECHO_OFF,
      &response, "%s: ", prompt_text);
  if (ret != PAM_SUCCESS) {
    pam_syslog(pamh, LOG_CRIT, "conversation error");
    return PAM_CONV_ERR;
  }
  if ((response != NULL) && (strcasecmp(response, want) == 0)) {
    ret = PAM_SUCCESS;
  } else {
    ret = PAM_AUTH_ERR;
  }
  if (response) {
    _pam_overwrite(response);
    free(response);
  }
  return ret;
}
Exemplo n.º 25
0
/**
 * @brief Check for allowance to access the node at pspam plugin
 *
 * Check for the allowance of the user @a user coming from the remote
 * host @a rhost to access the local node. For this the local pspam
 * plugin will be accesses in order figure out if the user currently
 * has a running batch-job on the node or is marked as an adminuser.
 *
 * Access might be denied (i.e. PSPAM_RES_DENY is returned) if the
 * communication to the pspam plugin fails or some problem in the
 * answer is detected. Otherwise pspam plugin's decision is returned.
 *
 * @param uName Username of the user to check
 *
 * @param rhost Hostname the user is coming from
 *
 * @return pspam plugin's decision is returned unless the
 * communication to the plugin failed. In the latter case
 * PSPAM_RES_DENY is returned (which might be a proper answer of the
 * pspam plugin, too).
 */
static PSPAMResult_t checkPsPamAllowance(const char *uName, const char *rhost)
{
    int sock = openConnection(pspamSocketName);
    PSPAMResult_t res;
    PS_SendDB_t data = { .bufUsed = 0, .useFrag = false };
    int written;

    if (sock == -1) {
	elog("connection to local plugin failed: %s", strerror(errno));
	return PSPAM_RES_DENY;
    }

    initSerialBuf(0);

    /* add length placeholder */
    addInt32ToMsg(0, &data);
    /* add command */
    addInt32ToMsg(PSPAM_CMD_SESS_OPEN, &data);
    /* add ssh pid */
    addPidToMsg(getpid(), &data);
    /* add ssh sid */
    addPidToMsg(getsid(0), &data);
    /* add username */
    addStringToMsg(uName, &data);
    /* add remote host */
    addStringToMsg(rhost, &data);

    /* add correct msg len (without length) at placeholder */
    *(int32_t *)data.buf = data.bufUsed - sizeof(int32_t);

    written = writeToPspam(sock, data.buf, data.bufUsed);

    finalizeSerial();

    if (written != (int)data.bufUsed) {
	elog("sending pspam auth request failed");
	return PSPAM_RES_DENY;
    }

    if (verbose > 2) {
	ilog("sending req(%i): %s@%s pid %u", sock, uName, rhost, getpid());
    }

    if (!readFromPspam(sock, &res, sizeof(res))) {
	close(sock);
	return PSPAM_RES_DENY;
    }
    close(sock);

    if (verbose > 2) {
	ilog("reply(%i): %s@%s res %u", sock, uName, rhost, res);
    }
    return res;
}

/**
 * @brief Check for allowance to access the node
 *
 * Check for the allowance of the user @a user coming from the remote
 * host @a rhost to access the local node. Allowance is granted either
 * via a white-list of usernames passed as an option to the PAM module
 * or by the local pspam plugin which might be contacted.
 *
 * @param uName Username of the user to check
 *
 * @param rhost Hostname the user is coming from
 *
 * @return PAM_SUCCESS is returned in order to grant access. Otherwise
 * PAM_AUTH_ERR is returned.
 */
static int checkAllowance(const char *uName, const char *rhost)
{
    PSPAMResult_t res;

    /* check if the user is in the authorized user list */
    if (isAuthorizedUser(uName)) {
	if (verbose > 1) {
	    ilog("grant access to %s@%s (authorized list)", uName, rhost);
	}
	return PAM_SUCCESS;
    }

    /* ask pspam if user has a batch job running and is allowed to connect */
    res = checkPsPamAllowance(uName, rhost);

    switch (res) {
    case PSPAM_RES_BATCH:
    case PSPAM_RES_ADMIN_USER:
	if (verbose > 1) {
	    ilog("grant access to %s@%s (%s)", uName, rhost,
		 (res == PSPAM_RES_BATCH) ? "batch job" : "ps admin user");
	}
	return PAM_SUCCESS;
    case PSPAM_RES_DENY:
    case PSPAM_RES_PROLOG:
	if (verbose > 0) {
	    ilog("deny access to %s@%s (%s)", uName, rhost,
		 (res == PSPAM_RES_PROLOG) ? "prologue" : "no job");
	}
    }

    if (!quiet) {
	char hName[HOSTNAME_LEN];

	if (gethostname(hName, sizeof(hName)) == -1) {
	    strncpy(hName, "this node", sizeof(hName));
	}

	switch (res) {
	case PSPAM_RES_DENY:
	    pam_prompt(pamH, PAM_TEXT_INFO, NULL, "\npspam: user '%s' without"
		       " running jobs on %s, access denied.\n",	uName, hName);
	    break;
	case PSPAM_RES_PROLOG:
	    pam_prompt(pamH, PAM_TEXT_INFO, NULL, "\npspam: prologue running on"
		       " %s, access denied.\n", hName);
	    break;
	default:
	    pam_prompt(pamH, PAM_TEXT_INFO, NULL, "\npspam: access denied.\n");
	}
    }

    return PAM_AUTH_ERR;
}