Beispiel #1
0
PAM_EXTERN int
pam_sm_authenticate(pam_handle_t *pamh, int flags,
  int argc, const char *argv[])
{
#ifndef _OPENPAM
  const void *ptr;
  const struct pam_conv *conv;
  struct pam_message msg;
  const struct pam_message *msgp;
  struct pam_response *resp;
#endif
  struct passwd *pwd;
  const char *user;
  char *pad;
  int pam_err, retry;

  FILE *file = NULL;
  char *pw = NULL, *offset = NULL, *num = NULL;

  /* identify user */
  if ((pam_err = pam_get_user(pamh, &user, NULL)) != PAM_SUCCESS)
    return (pam_err);
  if ((pwd = getpwnam(user)) == NULL)
    return (PAM_USER_UNKNOWN);

  /* get password */
#ifndef _OPENPAM
  pam_err = pam_get_item(pamh, PAM_CONV, &ptr);
  if (pam_err != PAM_SUCCESS)
    return (PAM_SYSTEM_ERR);
  conv = ptr;
  msg.msg_style = PAM_PROMPT_ECHO_ON;
  msg.msg = password_prompt;
  msgp = &msg;
#endif
  pad = NULL;
  for (retry = 0; retry < 3; ++retry) {
#ifdef _OPENPAM
    pam_err = pam_get_authtok(pamh, PAM_AUTHTOK,
        (const char **)&pad, NULL);
#else
    resp = NULL;
    pam_err = (*conv->conv)(1, &msgp, &resp, conv->appdata_ptr);
    if (resp != NULL) {
      if (pam_err == PAM_SUCCESS)
        pad = resp->resp;
      else
        free(resp->resp);
      free(resp);
    }
  // change to PAM_PROMPT_ECHO_OFF, if you want no password-echo
  msg.msg_style = PAM_PROMPT_ECHO_ON;
#endif
    if (pam_err == PAM_SUCCESS)
      break;
  }

  if (pam_err == PAM_CONV_ERR)
    return (pam_err);
  if (pam_err != PAM_SUCCESS)
    return (PAM_AUTH_ERR);

  // open file
  if((file = fopen(PASSWD_FILE, "r+")) == NULL)
    return PAM_AUTH_ERR;

  // parse file
  if(_parse_passwd(file, user, &pw, &offset, &num) != 0)
    return _cleanup(file, PAM_AUTH_ERR);

  // check, if authentication is successfull
  int i;
  if((i = openkubus_authenticate(pad, pw, atoi(offset), atoi(num))) > 0)
  {
    // update number in password file
    _update_passwd(file, num, i+1);

    return _cleanup(file, PAM_SUCCESS);
  }

  return _cleanup(file, PAM_AUTH_ERR);
}
static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
		       char *towhat, unsigned int ctrl, int remember)
{
	struct passwd *pwd = NULL;
	int retval = 0;

	D(("called"));

	setpwent();
	pwd = getpwnam(forwho);
	endpwent();

	if (pwd == NULL)
		return PAM_AUTHTOK_ERR;

	if (on(UNIX_NIS, ctrl)) {
		struct timeval timeout;
		struct yppasswd yppwd;
		CLIENT *clnt;
		char *master;
		int status;
		int err = 0;

		/* Make RPC call to NIS server */
		if ((master = getNISserver(pamh)) == NULL)
			return PAM_TRY_AGAIN;

		/* Initialize password information */
		yppwd.newpw.pw_passwd = pwd->pw_passwd;
		yppwd.newpw.pw_name = pwd->pw_name;
		yppwd.newpw.pw_uid = pwd->pw_uid;
		yppwd.newpw.pw_gid = pwd->pw_gid;
		yppwd.newpw.pw_gecos = pwd->pw_gecos;
		yppwd.newpw.pw_dir = pwd->pw_dir;
		yppwd.newpw.pw_shell = pwd->pw_shell;
		yppwd.oldpass = fromwhat;
		yppwd.newpw.pw_passwd = towhat;

		D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho));

		/* The yppasswd.x file said `unix authentication required',
		 * so I added it. This is the only reason it is in here.
		 * My yppasswdd doesn't use it, but maybe some others out there
		 * do.                                        --okir
		 */
		clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
		clnt->cl_auth = authunix_create_default();
		memset((char *) &status, '\0', sizeof(status));
		timeout.tv_sec = 25;
		timeout.tv_usec = 0;
		err = clnt_call(clnt, YPPASSWDPROC_UPDATE,
				(xdrproc_t) xdr_yppasswd, (char *) &yppwd,
				(xdrproc_t) xdr_int, (char *) &status,
				timeout);

		if (err) {
			clnt_perrno(err);
			retval = PAM_TRY_AGAIN;
		} else if (status) {
			fprintf(stderr, "Error while changing NIS password.\n");
			retval = PAM_TRY_AGAIN;
		}
		printf("\nThe password has%s been changed on %s.\n",
		       (err || status) ? " not" : "", master);

		auth_destroy(clnt->cl_auth);
		clnt_destroy(clnt);
		if ((err || status) != 0) {
			retval = PAM_TRY_AGAIN;
		}
#ifdef DEBUG
		sleep(5);
#endif
		return retval;
	}
	/* first, save old password */
	if (save_old_password(forwho, fromwhat, remember)) {
		return PAM_AUTHTOK_ERR;
	}
	if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) {
		retval = _update_shadow(forwho, towhat);
		if (retval == PAM_SUCCESS)
			retval = _update_passwd(forwho, "x");
	} else {
		retval = _update_passwd(forwho, towhat);
	}

	return retval;
}