コード例 #1
2
ファイル: pam.c プロジェクト: 2014-class/freerouter
static void
set_tkt_string(uid_t uid)
{
  char buf[128];

  snprintf(buf, sizeof(buf), "%s%u", TKT_ROOT, (unsigned)uid);
  krb_set_tkt_string(buf);

#if 0
  /* pam_set_data+pam_get_data are not guaranteed to work, grr. */
  pam_set_data(pamh, "KRBTKFILE", strdup(t), cleanup);
  if (pam_get_data(pamh, "KRBTKFILE", (const void**)&tkt) == PAM_SUCCESS)
    {
      pam_putenv(pamh, var);
    }
#endif

  /* We don't want to inherit this variable.
   * If we still do, it must have a sane value. */
  if (getenv("KRBTKFILE") != 0)
    {
      char *var = malloc(sizeof(buf));
      snprintf(var, sizeof(buf), "KRBTKFILE=%s", tkt_string());
      putenv(var);
      /* free(var); XXX */
    }
}
コード例 #2
0
ファイル: pam_gss.c プロジェクト: PADL/pam_gss
static int
pamGssAcquireCred(pam_handle_t *pamh,
                  int confFlags,
                  gss_name_t userName,
                  gss_buffer_t passwordBuf,
                  gss_OID mech,
                  gss_cred_id_t *cred)
{
    int status;
    OM_uint32 major, minor;
    gss_OID_set_desc mechOids;
#ifdef __APPLE__
    CFDictionaryRef attributes = NULL;

    status = pam_get_data(pamh, CREDUI_ATTR_DATA, (const void **)&attributes);
    if (status == PAM_SUCCESS)
        return pamGssAcquireAaplInitialCred(pamh, userName, mech, attributes, cred);
#endif /* __APPLE__ */

    mechOids.count = 1;
    mechOids.elements = mech;

    major = gss_acquire_cred_with_password(&minor, userName, passwordBuf,
                                           GSS_C_INDEFINITE, &mechOids,
                                           GSS_C_INITIATE, cred, NULL, NULL);
    BAIL_ON_GSS_ERROR(major, minor);

    status = PAM_SUCCESS;

cleanup:
    return status;
}
コード例 #3
0
ファイル: pam.c プロジェクト: silkentrance/nss-pam-ldap
/* try to get the module's context, returns a PAM status code */
static int ctx_get(pam_handle_t *pamh,const char *username,struct pld_ctx **pctx)
{
  struct pld_ctx *ctx=NULL;
  int rc;
  /* try to get the context from PAM */
  rc=pam_get_data(pamh,PLD_CTX,(const void **)&ctx);
  if ((rc==PAM_SUCCESS)&&(ctx!=NULL))
  {
    /* if the user is different clear the context */
    if ((ctx->user!=NULL)&&(strcmp(ctx->user,username)!=0))
      ctx_clear(ctx);
  }
  else
  {
    /* allocate a new context */
    ctx=calloc(1,sizeof(struct pld_ctx));
    if (ctx==NULL)
    {
      pam_syslog(pamh,LOG_CRIT,"calloc(): failed to allocate memory: %s",strerror(errno));
      return PAM_BUF_ERR;
    }
    ctx_clear(ctx);
    /* store the new context with the handler to free it */
    rc=pam_set_data(pamh,PLD_CTX,ctx,ctx_free);
    if (rc!=PAM_SUCCESS)
    {
      ctx_free(pamh,ctx,0);
      pam_syslog(pamh,LOG_ERR,"failed to store context: %s",pam_strerror(pamh,rc));
      return rc;
    }
  }
  /* return the context */
  *pctx=ctx;
  return PAM_SUCCESS;
}
コード例 #4
0
PAM_EXTERN int
pam_sm_open_session (pam_handle_t *ph, int flags, int argc, const char **argv)
{
	const char *user = NULL, *password = NULL;
	struct passwd *pwd;
	int ret;
	uint args;
	int started_daemon;

	args = parse_args (ph, argc, argv);

	if (args & ARG_IGNORE_SERVICE)
		return PAM_SUCCESS;

	/* Figure out the user name */
	ret = pam_get_user (ph, &user, NULL);
	if (ret != PAM_SUCCESS) {
		syslog (GKR_LOG_ERR, "gkr-pam: couldn't get the user name: %s", 
		        pam_strerror (ph, ret));
		return PAM_SERVICE_ERR;
	}

	pwd = getpwnam (user);
	if (!pwd) {
		syslog (GKR_LOG_ERR, "gkr-pam: error looking up user information for: %s", user);
		return PAM_SERVICE_ERR;
	}

	/* Get the stored authtok here */
	if (pam_get_data (ph, "gkr_system_authtok", (const void**)&password) != PAM_SUCCESS) {
		/* 
		 * No password, no worries, maybe this (PAM using) application 
		 * didn't do authentication, or is hopeless and wants to call 
		 * different PAM callbacks from different processes.
		 * 
		 * No use complaining
		 */
		password = NULL;
	}
	
	started_daemon = 0;
	
	/* Should we start the daemon? */
	if (args & ARG_AUTO_START) {
		ret = start_daemon_if_necessary (ph, pwd, password, &started_daemon);
		if (ret != PAM_SUCCESS)
			return ret;
	}

	/* If mate keyring is running, but we didn't start it here, then unlock now */
	if (get_any_env (ph, ENV_CONTROL) != NULL) {
		if (!started_daemon && password != NULL) {
			if (unlock_keyring (ph, pwd, password) != PAM_SUCCESS)
				return PAM_SERVICE_ERR;
		}
	}
	
	return PAM_SUCCESS;
}
コード例 #5
0
ファイル: pam_encfs.c プロジェクト: x-itec/pam-encfs
PAM_EXTERN int pam_sm_close_session(pam_handle_t * pamh,
                                    int flags, int argc, const char **argv)
{

    int retval;
    pid_t pid;
    char *targetpath;
    char *args[4];

    //  _pam_log(LOG_ERR,"Geteuid : %d",geteuid());

    if ((retval =
         pam_get_data(pamh, "encfs_targetpath",
                      (const void **) &targetpath)) != PAM_SUCCESS)
        return retval;

    if (!checkmnt(targetpath))
    {
        _pam_log(LOG_ERR, "Targetpath is not mounted!: %s", targetpath);
        return PAM_SERVICE_ERR;
    }

    args[0] = "fusermount";
    args[1] = "-uz";
    args[2] = targetpath;
    args[3] = NULL;

    switch (pid = fork())
    {
        case -1:
            _pam_log(LOG_ERR, "Fork failed");
            return PAM_SERVICE_ERR;
        case 0:
            execvp("fusermount", args);
            char errstr[128];

            snprintf(errstr, 127, "%d - %s", errno, strerror(errno));
            _pam_log(LOG_ERR, "Exec failed - %s", errstr);
            exit(127);
    }

    if (waitpid(pid, NULL, 0) == -1)
      _pam_log(LOG_ERR, "Waitpid failed - %s", strerror(errno));

    /*We'll get this error every single time we have more than one session active, todo fix this with some better checks + support fuser -km if no more session connected.  
       if (checkmnt(targetpath)) {
       _pam_log(LOG_ERR,"Failed to unmount %s",targetpath);
       return PAM_SERVICE_ERR;
       } */

    return PAM_IGNORE;
}
コード例 #6
0
PAM_EXTERN int
pam_sm_open_session(pam_handle_t *pamh, int flags,
                    int argc, const char *argv[])
{
    const char *user;
    const void *data;

    if (pam_get_user(pamh, &user, NULL) == PAM_SUCCESS &&
            pam_get_data(pamh, "pam_auth_ticket", &data) == PAM_SUCCESS)
        write_ticket(user, (const char*)data);

    return (PAM_SUCCESS);
}
コード例 #7
0
ファイル: pam_gss.c プロジェクト: PADL/pam_gss
PAM_EXTERN int
pam_sm_setcred(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
    int status;
    OM_uint32 major, minor;
    gss_cred_id_t cred = GSS_C_NO_CREDENTIAL;
    gss_OID mech = GSS_C_NO_OID;

    if (flags && (flags & PAM_ESTABLISH_CRED) == 0)
        return PAM_SUCCESS;

    status = pam_get_data(pamh, GSS_CRED_DATA, (const void **)&cred);
    BAIL_ON_PAM_ERROR(status);

    status = pam_get_data(pamh, GSS_MECH_DATA, (const void **)&mech);
    BAIL_ON_PAM_ERROR(status);

    major = gss_store_cred(&minor, cred, GSS_C_INITIATE, mech,
                           1, 1, NULL, NULL);
    BAIL_ON_GSS_ERROR(major, minor);

cleanup:
    return status;
}
コード例 #8
0
int pam_sm_setcred(pam_handle_t *pamh, int flags,
                   int argc, const char **argv)
{
    int retval, *pretval = NULL;

    retval = PAM_SUCCESS;

    pam_get_data(pamh, "smb_setcred_return", (const void **) &pretval);
    if(pretval) {
	retval = *pretval;
	SAFE_FREE(pretval);
    }
    pam_set_data(pamh, "smb_setcred_return", NULL, NULL);

    return retval;
}
コード例 #9
0
ファイル: pam_kwallet.c プロジェクト: amaramrahul/pam-kwallet
PAM_EXTERN int pam_sm_open_session(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
    pam_syslog(pamh, LOG_INFO, "pam_sm_open_session\n");

    if (get_env(pamh, "PAM_KWALLET_LOGIN") != NULL) {
        pam_syslog(pamh, LOG_INFO, "pam_kwallet: we were already executed");
        return PAM_SUCCESS;
    }

    parseArguments(argc, argv);

    int result;
    result = pam_set_data(pamh, "sm_open_session", "1", NULL);
    if (result != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Impossible to store sm_open_session: %s"
            , pam_strerror(pamh, result));
        return PAM_IGNORE;
    }

     //Fetch the user, needed to get user information
    const char *username;
    result = pam_get_user(pamh, &username, NULL);
    if (result != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Couldn't get username %s",
                   pam_strerror(pamh, result));
        return PAM_IGNORE;//Since we are not an essential module, just make pam ignore us
    }

    struct passwd *userInfo;
    userInfo = getpwnam(username);
    if (!userInfo) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Couldn't get user info (passwd) info");
        return PAM_IGNORE;
    }

    const char *kwalletKey;
    result = pam_get_data(pamh, "kwallet_key", (const void **)&kwalletKey);

    if (result != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_INFO, "pam_kwallet: open_session called without kwallet_key");
        return PAM_SUCCESS;//We will wait for pam_sm_authenticate
    }

    start_kwallet(pamh, userInfo, kwalletKey);

    return PAM_SUCCESS;
}
コード例 #10
0
int
openpam_borrow_cred(pam_handle_t *pamh,
	const struct passwd *pwd)
{
	struct pam_saved_cred *scred;
	const void *scredp;
	int r;

	ENTERI(pwd->pw_uid);
	r = pam_get_data(pamh, PAM_SAVED_CRED, &scredp);
	if (r == PAM_SUCCESS && scredp != NULL) {
		openpam_log(PAM_LOG_DEBUG,
		    "already operating under borrowed credentials");
		RETURNC(PAM_SYSTEM_ERR);
	}
	if (geteuid() != 0 && geteuid() != pwd->pw_uid) {
		openpam_log(PAM_LOG_DEBUG, "called with non-zero euid: %d",
		    (int)geteuid());
		RETURNC(PAM_PERM_DENIED);
	}
	scred = calloc((size_t)1, sizeof *scred);
	if (scred == NULL)
		RETURNC(PAM_BUF_ERR);
	scred->euid = geteuid();
	scred->egid = getegid();
	r = getgroups(NGROUPS_MAX, scred->groups);
	if (r < 0) {
		FREE(scred);
		RETURNC(PAM_SYSTEM_ERR);
	}
	scred->ngroups = r;
	r = pam_set_data(pamh, PAM_SAVED_CRED, scred, &openpam_free_data);
	if (r != PAM_SUCCESS) {
		FREE(scred);
		RETURNC(r);
	}
	if (geteuid() == pwd->pw_uid)
		RETURNC(PAM_SUCCESS);
	if (initgroups(pwd->pw_name, pwd->pw_gid) < 0 ||
	      setegid(pwd->pw_gid) < 0 || seteuid(pwd->pw_uid) < 0) {
		openpam_restore_cred(pamh);
		RETURNC(PAM_SYSTEM_ERR);
	}
	RETURNC(PAM_SUCCESS);
	/*NOTREACHED*/
}
コード例 #11
0
ファイル: pam_gss.c プロジェクト: PADL/pam_gss
PAM_EXTERN int
pam_sm_acct_mgmt(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
    int status;
    gss_name_t canonUserName = GSS_C_NO_NAME;
    char *userName = NULL;

    status = pam_get_data(pamh, GSS_NAME_DATA, (const void **)&canonUserName);
    if (status != PAM_SUCCESS)
        return PAM_USER_UNKNOWN;

    status = pam_get_user(pamh, (void *)&userName, NULL);
    if (status != PAM_SUCCESS)
        return PAM_USER_UNKNOWN;

    return gss_userok(canonUserName, userName) ? PAM_SUCCESS : PAM_PERM_DENIED;

}
コード例 #12
0
int
openpam_restore_cred(pam_handle_t *pamh)
{
	struct pam_saved_cred *scred;
	int r;

	r = pam_get_data(pamh, PAM_SAVED_CRED, (const void **)(void *)&scred);
	if (r != PAM_SUCCESS)
		return (r);
	if (scred == NULL)
		return (PAM_SYSTEM_ERR);
	if (seteuid(scred->euid) == -1 ||
	    setgroups(scred->ngroups, scred->groups) == -1 ||
	    setegid(scred->egid) == -1)
		return (PAM_SYSTEM_ERR);
	pam_set_data(pamh, PAM_SAVED_CRED, NULL, NULL);
	return (PAM_SUCCESS);
}
コード例 #13
0
ファイル: pam_credui.cpp プロジェクト: PADL/CredUI
static int
_PAMCreateAttributesFromHandle(pam_handle_t *pamh, CFDictionaryRef *pAttributes)
{
    CFMutableDictionaryRef attributes = NULL;
    const char *user;
    int rc;

    rc = pam_get_item(pamh, PAM_USER, (const void **)&user);
    if (rc != PAM_SUCCESS)
        return rc;

    CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, user, kCFStringEncodingUTF8);
    if (name == NULL) {
        CFRelease(attributes);
        return PAM_BUF_ERR;
    }

    /* In case module returned PAM_TRY_AGAIN */
    rc = pam_get_data(pamh, CREDUI_ATTR_DATA, (const void **)&attributes);
    if (rc == PAM_SUCCESS && attributes) {
        CFStringRef assertedName = (CFStringRef)CFDictionaryGetValue(attributes, kCUIAttrName);
        
        if (assertedName && CFEqual(assertedName, name)) {
            *pAttributes = (CFDictionaryRef)CFRetain(attributes);
            CFRelease(name);
            return PAM_SUCCESS;
        }
    }
    
    attributes = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
    if (attributes == NULL)
        return PAM_BUF_ERR;
    
    CFDictionarySetValue(attributes, kCUIAttrNameType, kCUIAttrNameTypePosixName);
    CFDictionarySetValue(attributes, kCUIAttrName, name);
    
    /* we don't get AUTHTOK because it might prompt */
    
    CFRelease(name);
    
    *pAttributes = attributes;
    return PAM_SUCCESS;
}
コード例 #14
0
ファイル: pam_yubikey.c プロジェクト: asirinelli/yubikey_zmq
PAM_EXTERN int
pam_sm_setcred (pam_handle_t * pamh, int flags, int argc, const char **argv)
{
  int retval;
  const void *pretval = NULL;

  DBG (("called."));

  retval = PAM_SUCCESS;
  if (pam_get_data(pamh, "yubikey_setcred_return", &pretval) == PAM_SUCCESS
      && pretval)
    {
      retval = *(const int *)pretval;
      pam_set_data(pamh, "yubikey_setcred_return", NULL, NULL);
    }

  DBG (("done. [%s]", pam_strerror (pamh, retval)));

  return retval;
}
コード例 #15
0
static int
stop_daemon (pam_handle_t *ph, struct passwd *pwd)
{
	const char *spid = NULL;
	char *apid = NULL;
	pid_t pid;
	
	assert (pwd);

	pam_get_data (ph, "gkr-pam-pid", (const void**)&spid);
	
	/* 
	 * No pid, no worries, maybe we didn't start mate-keyring-daemon
	 * Or this the calling (PAM using) application is hopeless and 
	 * wants to call different PAM callbacks from different processes.
	 * 
	 * In any case we live and let live.
	 */
	if (!spid)
		goto done;
	
	/* Make sure it parses out nicely */
	pid = (pid_t)atoi (spid);
	if (pid <= 0) {
		syslog (GKR_LOG_ERR, "gkr-pam: invalid mate-keyring-daemon process id: %s", spid);
		goto done;
	}
	
    	if (kill (pid, SIGTERM) < 0 && errno != ESRCH) {
    		syslog (GKR_LOG_ERR, "gkr-pam: couldn't kill mate-keyring-daemon process %d: %s", 
    		        (int)pid, strerror (errno));
    		goto done;
    	}    		

done:
	free_safe (apid);
	
	/* Don't bother user when daemon can't be stopped */
	return PAM_SUCCESS;
}
コード例 #16
0
int
openpam_restore_cred(pam_handle_t *pamh)
{
	const struct pam_saved_cred *scred;
	const void *scredp;
	int r;

	ENTER();
	r = pam_get_data(pamh, PAM_SAVED_CRED, &scredp);
	if (r != PAM_SUCCESS)
		RETURNC(r);
	if (scredp == NULL)
		RETURNC(PAM_SYSTEM_ERR);
	scred = scredp;
	if (scred->euid != geteuid()) {
		if (seteuid(scred->euid) < 0 ||
		    setgroups(scred->ngroups, scred->groups) < 0 ||
		    setegid(scred->egid) < 0)
			RETURNC(PAM_SYSTEM_ERR);
	}
	pam_set_data(pamh, PAM_SAVED_CRED, NULL, NULL);
	RETURNC(PAM_SUCCESS);
}
コード例 #17
0
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
				int argc, const char **argv)
{
	unsigned int ctrl, lctrl;
	int retval, i;
	int remember = -1;

	/* <DO NOT free() THESE> */
	const char *user;
	char *pass_old, *pass_new;
	/* </DO NOT free() THESE> */

	D(("called."));

#ifdef USE_LCKPWDF
	/* our current locking system requires that we lock the
	   entire password database.  This avoids both livelock
	   and deadlock. */
	/* These values for the number of attempts and the sleep time
	   are, of course, completely arbitrary.
	   My reading of the PAM docs is that, once pam_chauthtok() has been
	   called with PAM_UPDATE_AUTHTOK, we are obliged to take any
	   reasonable steps to make sure the token is updated; so retrying
	   for 1/10 sec. isn't overdoing it.
	   The other possibility is to call lckpwdf() on the first
	   pam_chauthtok() pass, and hold the lock until released in the
	   second pass--but is this guaranteed to work? -SRL */
	i=0;
	while((retval = lckpwdf()) != 0 && i < 100) {
		usleep(1000);
	}
	if(retval != 0) {
		return PAM_AUTHTOK_LOCK_BUSY;
	}
#endif
	ctrl = _set_ctrl(pamh, flags, &remember, argc, argv);

	/*
	 * First get the name of a user
	 */
	retval = pam_get_user(pamh, &user, "Username: "******"bad username [%s]", user);
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return PAM_USER_UNKNOWN;
		}
		if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
			_log_err(LOG_DEBUG, pamh, "username [%s] obtained",
			         user);
	} else {
		if (on(UNIX_DEBUG, ctrl))
			_log_err(LOG_DEBUG, pamh,
			         "password - could not identify user");
#ifdef USE_LCKPWDF
		ulckpwdf();
#endif
		return retval;
	}

	D(("Got username of %s", user));

	/*
	 * This is not an AUTH module!
	 */
	if (on(UNIX__NONULL, ctrl))
		set(UNIX__NULLOK, ctrl);

	if (on(UNIX__PRELIM, ctrl)) {
		/*
		 * obtain and verify the current password (OLDAUTHTOK) for
		 * the user.
		 */
		char *Announce;

		D(("prelim check"));

		if (_unix_blankpasswd(ctrl, user)) {
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return PAM_SUCCESS;
		} else if (off(UNIX__IAMROOT, ctrl)) {

			/* instruct user what is happening */
#define greeting "Changing password for "
			Announce = (char *) malloc(sizeof(greeting) + strlen(user));
			if (Announce == NULL) {
				_log_err(LOG_CRIT, pamh,
				         "password - out of memory");
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return PAM_BUF_ERR;
			}
			(void) strcpy(Announce, greeting);
			(void) strcpy(Announce + sizeof(greeting) - 1, user);
#undef greeting

			lctrl = ctrl;
			set(UNIX__OLD_PASSWD, lctrl);
			retval = _unix_read_password(pamh, lctrl
						     ,Announce
					     ,"(current) UNIX password: "******"password - (old) token not obtained");
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return retval;
			}
			/* verify that this is the password for this user */

			retval = _unix_verify_password(pamh, user, pass_old, ctrl);
		} else {
			D(("process run by root so do nothing this time around"));
			pass_old = NULL;
			retval = PAM_SUCCESS;	/* root doesn't have too */
		}

		if (retval != PAM_SUCCESS) {
			D(("Authentication failed"));
			pass_old = NULL;
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
		pass_old = NULL;
		if (retval != PAM_SUCCESS) {
			_log_err(LOG_CRIT, pamh,
			         "failed to set PAM_OLDAUTHTOK");
		}
		retval = _unix_verify_shadow(user, ctrl);
		if (retval == PAM_AUTHTOK_ERR) {
			if (off(UNIX__IAMROOT, ctrl))
				_make_remark(pamh, ctrl, PAM_ERROR_MSG,
					    "You must wait longer to change your password");
			else
				retval = PAM_SUCCESS;
		}
	} else if (on(UNIX__UPDATE, ctrl)) {
		/*
		 * tpass is used below to store the _pam_md() return; it
		 * should be _pam_delete()'d.
		 */

		char *tpass = NULL;
		int retry = 0;

		/*
		 * obtain the proposed password
		 */

		D(("do update"));

		/*
		 * get the old token back. NULL was ok only if root [at this
		 * point we assume that this has already been enforced on a
		 * previous call to this function].
		 */

		if (off(UNIX_NOT_SET_PASS, ctrl)) {
			retval = pam_get_item(pamh, PAM_OLDAUTHTOK
					      ,(const void **) &pass_old);
		} else {
			retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK
					      ,(const void **) &pass_old);
			if (retval == PAM_NO_MODULE_DATA) {
				retval = PAM_SUCCESS;
				pass_old = NULL;
			}
		}
		D(("pass_old [%s]", pass_old));

		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh, "user not authenticated");
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		retval = _unix_verify_shadow(user, ctrl);
		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh, "user not authenticated 2");
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		D(("get new password now"));

		lctrl = ctrl;

		if (on(UNIX_USE_AUTHTOK, lctrl)) {
			set(UNIX_USE_FIRST_PASS, lctrl);
		}
		retry = 0;
		retval = PAM_AUTHTOK_ERR;
		while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) {
			/*
			 * use_authtok is to force the use of a previously entered
			 * password -- needed for pluggable password strength checking
			 */

			retval = _unix_read_password(pamh, lctrl
						     ,NULL
					     ,"Enter new UNIX password: "******"Retype new UNIX password: "******"password - new password not obtained");
				}
				pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
				ulckpwdf();
#endif
				return retval;
			}
			D(("returned to _unix_chauthtok"));

			/*
			 * At this point we know who the user is and what they
			 * propose as their new password. Verify that the new
			 * password is acceptable.
			 */

			if (pass_new[0] == '\0') {	/* "\0" password = NULL */
				pass_new = NULL;
			}
			retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new);
		}

		if (retval != PAM_SUCCESS) {
			_log_err(LOG_NOTICE, pamh,
			         "new password not acceptable");
			_pam_overwrite(pass_new);
			_pam_overwrite(pass_old);
			pass_new = pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
			ulckpwdf();
#endif
			return retval;
		}
		/*
		 * By reaching here we have approved the passwords and must now
		 * rebuild the password database file.
		 */

		/*
		 * First we encrypt the new password.
		 */

		if (on(UNIX_MD5_PASS, ctrl)) {
			tpass = crypt_md5_wrapper(pass_new);
		} else {
			/*
			 * Salt manipulation is stolen from Rick Faith's passwd
			 * program.  Sorry Rick :) -- alex
			 */

			time_t tm;
			char salt[3];

			time(&tm);
			salt[0] = bin_to_ascii(tm & 0x3f);
			salt[1] = bin_to_ascii((tm >> 6) & 0x3f);
			salt[2] = '\0';

			if (off(UNIX_BIGCRYPT, ctrl) && strlen(pass_new) > 8) {
				/* 
				 * to avoid using the _extensions_ of the bigcrypt()
				 * function we truncate the newly entered password
				 */
				char *temp = malloc(9);
				char *e;

				if (temp == NULL) {
					_log_err(LOG_CRIT, pamh,
					         "out of memory for password");
					_pam_overwrite(pass_new);
					_pam_overwrite(pass_old);
					pass_new = pass_old = NULL;	/* tidy up */
#ifdef USE_LCKPWDF
					ulckpwdf();
#endif
					return PAM_BUF_ERR;
				}
				/* copy first 8 bytes of password */
				strncpy(temp, pass_new, 8);
				temp[8] = '\0';

				/* no longer need cleartext */
				e = bigcrypt(temp, salt);
				tpass = x_strdup(e);

				_pam_overwrite(e);
				_pam_delete(temp);	/* tidy up */
			} else {
				char *e;

				/* no longer need cleartext */
				e = bigcrypt(pass_new, salt);
				tpass = x_strdup(e);

				_pam_overwrite(e);
			}
		}

		D(("password processed"));

		/* update the password database(s) -- race conditions..? */

		retval = _do_setpass(pamh, user, pass_old, tpass, ctrl,
		                     remember);
		_pam_overwrite(pass_new);
		_pam_overwrite(pass_old);
		_pam_delete(tpass);
		pass_old = pass_new = NULL;
	} else {		/* something has broken with the module */
コード例 #18
0
ファイル: krb5_password.c プロジェクト: andreiw/polaris
int
pam_sm_chauthtok(
	pam_handle_t		*pamh,
	int			flags,
	int			argc,
	const char		**argv)
{

	char			*user;
	int			err, result = PAM_AUTH_ERR;
	char			*newpass = NULL, *vnewpass = NULL;
	char			*oldpass = NULL;
	int			i;
	int			debug = 0;
	uid_t			pw_uid;
	krb5_module_data_t	*kmd = NULL;
	char			*pam_service;
	int			promptforold = 0;
	int			promptfornew = 0;
	pam_repository_t	*rep_data = NULL;

	for (i = 0; i < argc; i++) {
		if (strcmp(argv[i], "debug") == 0)
			debug = 1;
		else
			syslog(LOG_ERR,
			    dgettext(TEXT_DOMAIN,
				    "PAM-KRB5 (password): illegal option %s"),
			    argv[i]);
	}

	if (debug)
		syslog(LOG_DEBUG,
		    "PAM-KRB5 (password): start: flags = %x",
		    flags);

	err = pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data);
	if (rep_data != NULL) {
		if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) {
			if (debug)
				syslog(LOG_DEBUG, "PAM-KRB5 (auth): wrong"
					"repository found (%s), returning "
					"PAM_IGNORE", rep_data->type);
			return (PAM_IGNORE);
		}
	}

	if (flags & PAM_PRELIM_CHECK) {
		/* Nothing to do here */
		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5 (password): prelim check");
		return (PAM_IGNORE);
	}

	/* make sure PAM framework is telling us to update passwords */
	if (!(flags & PAM_UPDATE_AUTHTOK)) {
		syslog(LOG_ERR, dgettext(TEXT_DOMAIN,
			"PAM-KRB5 (password): bad flags: %d"),
			flags);
		return (PAM_SYSTEM_ERR);
	}


	if ((err = pam_get_data(pamh, KRB5_DATA, (const void **)&kmd))
	    != PAM_SUCCESS) {
		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5 (password): get mod data failed %d",
			    err);
		kmd = NULL;
	}

	if (flags & PAM_CHANGE_EXPIRED_AUTHTOK) {
		/* let's make sure we know the krb5 pw has expired */

		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5 (password): kmd age status %d",
			    kmd ? kmd->age_status : -99);

		if (!kmd || kmd->age_status != PAM_NEW_AUTHTOK_REQD)
			return (PAM_IGNORE);
	}

	err = pam_get_item(pamh, PAM_SERVICE, (void **)&pam_service);
	if (err != PAM_SUCCESS) {
		syslog(LOG_ERR,
		    "PAM-KRB5 (password): error getting SERVICE");
		return (PAM_SYSTEM_ERR);
	}

	err = pam_get_item(pamh, PAM_USER, (void **)&user);
	if (err != PAM_SUCCESS) {
		syslog(LOG_ERR,
		    "PAM-KRB5 (password): error getting USER");
		return (PAM_SYSTEM_ERR);
	}

	if (user == NULL || user == '\0') {
		syslog(LOG_ERR,
		    "PAM-KRB5 (password): username is empty");
		return (PAM_SYSTEM_ERR);
	}

	if (!get_pw_uid(user, &pw_uid)) {
		syslog(LOG_ERR,
		    "PAM-KRB5 (password): can't get uid for %s",
		    user);
		return (PAM_AUTHTOK_ERR);
	}

	/*
	 * if root key exists in the keytab, it's a random key so no
	 * need to prompt for pw and we just return IGNORE
	 */
	if ((strcmp(user, ROOT_UNAME) == 0) &&
	    key_in_keytab(user, debug)) {
		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5 (password): "
			    "key for '%s' in keytab, returning IGNORE", user);
		result = PAM_IGNORE;
		goto out;
	}

	if ((err = pam_get_item(pamh, PAM_AUTHTOK,
				(void **) &newpass)) < 0)
		return (err);

	if ((err = pam_get_item(pamh, PAM_OLDAUTHTOK,
				(void **) &oldpass)) < 0)
		return (err);

	if (!newpass && !oldpass) {
		promptforold = 1;
		promptfornew = 1;
	} else {
		/*
		 * OLDAUTHTOK not set, we're probably the first password
		 * module but the AUTHTOK is probably set from an auth mod
		 */
		if (newpass && !oldpass) {
			oldpass = newpass;
			newpass = NULL;
			promptfornew = 1;
		}

		result = krb5_verifypw(pamh, user, oldpass,
				    DONT_DISP_POLICY, debug);
		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5 (password): verifypw first %d",
			    result);
		/*
		 * If this fails and is not bad passwd, then it might
		 * be a non-rpcsec_gss KDC so drop thru.
		 *
		 * (note in S9 change pw should work on non-rpcsec_gss KDCs
		 *  such as MIT & MS)
		 */
		if (result != 0)
			promptforold = 1;
	}

	if (promptforold) {

		oldpass = get_passwd(pamh,
				    dgettext(TEXT_DOMAIN,
					    "Old Kerberos password: "******"Need the old password"
					    " to proceed \n"));
			free(oldpass);
			return (PAM_AUTHTOK_ERR);
		}

		result = krb5_verifypw(pamh, user, oldpass,
				    DISP_POLICY, debug);
		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5 (password): verifypw prforold %d",
			    result);
		/*
		 * If it's a bad password, we are done.
		 * Else, continue and try the pwch with oldpass.
		 */
		if (result == 2) {
			display_msg(pamh, PAM_ERROR_MSG,
				    dgettext(TEXT_DOMAIN,
					    "Old Kerberos"
					    " password incorrect\n"));
			(void) memset(oldpass, 0, strlen(oldpass));
			free(oldpass);
			return (PAM_AUTHTOK_ERR);
		}
	}

	if (promptfornew) {
		newpass = get_passwd(pamh, dgettext(TEXT_DOMAIN,
			"New Kerberos password: "******"Need a password to proceed \n"));
			result = PAM_AUTHTOK_ERR;
			goto out;
		}

		vnewpass = get_passwd(pamh,
				dgettext(TEXT_DOMAIN,
			"Re-enter new Kerberos password: "******"Need a password to proceed \n"));
			result = PAM_AUTHTOK_ERR;
			goto out;
		}

		if (strcmp(newpass, vnewpass)) {
			display_msg(pamh, PAM_ERROR_MSG,
			    dgettext(TEXT_DOMAIN,
				"Passwords do not match \n"));
			result = PAM_AUTHTOK_ERR;
			goto out;
		}
	}

	result = krb5_changepw(pamh, user, oldpass, newpass, debug);
	if (result == PAM_SUCCESS) {
		display_msg(pamh, PAM_TEXT_INFO,
			    dgettext(TEXT_DOMAIN,
				    "Kerberos password "
				    "successfully changed\n"));

		get_set_creds(pamh, kmd, user, newpass, debug);

		(void) pam_set_item(pamh, PAM_AUTHTOK, newpass);
		(void) pam_set_item(pamh, PAM_OLDAUTHTOK, oldpass);
	}

out:
	if (promptforold && oldpass) {
		(void) memset(oldpass, 0, strlen(oldpass));
		free(oldpass);
	}
	if (newpass) {
		(void) memset(newpass, 0, strlen(newpass));
		free(newpass);
	}

	if (vnewpass) {
		(void) memset(vnewpass, 0, strlen(vnewpass));
		free(vnewpass);
	}

	if (debug)
		syslog(LOG_DEBUG,
		    "PAM-KRB5 (password): out: returns %d",
		    result);

	return (result);
}
コード例 #19
0
PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
				int argc, const char **argv)
{
	unsigned int ctrl, lctrl;
	int retval;
	int remember = -1;
	int rounds = -1;
	int pass_min_len = 0;

	/* <DO NOT free() THESE> */
	const char *user;
	const void *pass_old, *pass_new;
	/* </DO NOT free() THESE> */

	D(("called."));

	ctrl = _set_ctrl(pamh, flags, &remember, &rounds, &pass_min_len,
	                 argc, argv);

	/*
	 * First get the name of a user
	 */
	retval = pam_get_user(pamh, &user, NULL);
	if (retval == PAM_SUCCESS) {
		/*
		 * Various libraries at various times have had bugs related to
		 * '+' or '-' as the first character of a user name. Don't
		 * allow them.
		 */
		if (user == NULL || user[0] == '-' || user[0] == '+') {
			pam_syslog(pamh, LOG_ERR, "bad username [%s]", user);
			return PAM_USER_UNKNOWN;
		}
		if (retval == PAM_SUCCESS && on(UNIX_DEBUG, ctrl))
			pam_syslog(pamh, LOG_DEBUG, "username [%s] obtained",
			         user);
	} else {
		if (on(UNIX_DEBUG, ctrl))
			pam_syslog(pamh, LOG_DEBUG,
			         "password - could not identify user");
		return retval;
	}

	D(("Got username of %s", user));

	/*
	 * Before we do anything else, check to make sure that the user's
	 * info is in one of the databases we can modify from this module,
	 * which currently is 'files' and 'nis'.  We have to do this because
	 * getpwnam() doesn't tell you *where* the information it gives you
	 * came from, nor should it.  That's our job.
	 */
	if (_unix_comesfromsource(pamh, user, 1, on(UNIX_NIS, ctrl)) == 0) {
		pam_syslog(pamh, LOG_DEBUG,
			 "user \"%s\" does not exist in /etc/passwd%s",
			 user, on(UNIX_NIS, ctrl) ? " or NIS" : "");
		return PAM_USER_UNKNOWN;
	} else {
		struct passwd *pwd;
		_unix_getpwnam(pamh, user, 1, 1, &pwd);
		if (pwd == NULL) {
			pam_syslog(pamh, LOG_DEBUG,
				"user \"%s\" has corrupted passwd entry",
				user);
			return PAM_USER_UNKNOWN;
		}
	}

	/*
	 * This is not an AUTH module!
	 */
	if (on(UNIX__NONULL, ctrl))
		set(UNIX__NULLOK, ctrl);

	if (on(UNIX__PRELIM, ctrl)) {
		/*
		 * obtain and verify the current password (OLDAUTHTOK) for
		 * the user.
		 */
		char *Announce;

		D(("prelim check"));

		if (_unix_blankpasswd(pamh, ctrl, user)) {
			return PAM_SUCCESS;
		} else if (off(UNIX__IAMROOT, ctrl)) {
			/* instruct user what is happening */
			if (asprintf(&Announce, _("Changing password for %s."),
				user) < 0) {
				pam_syslog(pamh, LOG_CRIT,
				         "password - out of memory");
				return PAM_BUF_ERR;
			}

			lctrl = ctrl;
			set(UNIX__OLD_PASSWD, lctrl);
			retval = _unix_read_password(pamh, lctrl
						     ,Announce
					     ,_("(current) UNIX password: "******"password - (old) token not obtained");
				return retval;
			}
			/* verify that this is the password for this user */

			retval = _unix_verify_password(pamh, user, pass_old, ctrl);
		} else {
			D(("process run by root so do nothing this time around"));
			pass_old = NULL;
			retval = PAM_SUCCESS;	/* root doesn't have too */
		}

		if (retval != PAM_SUCCESS) {
			D(("Authentication failed"));
			pass_old = NULL;
			return retval;
		}
		retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
		pass_old = NULL;
		if (retval != PAM_SUCCESS) {
			pam_syslog(pamh, LOG_CRIT,
			         "failed to set PAM_OLDAUTHTOK");
		}
		retval = _unix_verify_shadow(pamh,user, ctrl);
		if (retval == PAM_AUTHTOK_ERR) {
			if (off(UNIX__IAMROOT, ctrl))
				_make_remark(pamh, ctrl, PAM_ERROR_MSG,
					     _("You must wait longer to change your password"));
			else
				retval = PAM_SUCCESS;
		}
	} else if (on(UNIX__UPDATE, ctrl)) {
		/*
		 * tpass is used below to store the _pam_md() return; it
		 * should be _pam_delete()'d.
		 */

		char *tpass = NULL;
		int retry = 0;

		/*
		 * obtain the proposed password
		 */

		D(("do update"));

		/*
		 * get the old token back. NULL was ok only if root [at this
		 * point we assume that this has already been enforced on a
		 * previous call to this function].
		 */

		if (off(UNIX_NOT_SET_PASS, ctrl)) {
			retval = pam_get_item(pamh, PAM_OLDAUTHTOK
					      ,&pass_old);
		} else {
			retval = pam_get_data(pamh, _UNIX_OLD_AUTHTOK
					      ,&pass_old);
			if (retval == PAM_NO_MODULE_DATA) {
				retval = PAM_SUCCESS;
				pass_old = NULL;
			}
		}
		D(("pass_old [%s]", pass_old));

		if (retval != PAM_SUCCESS) {
			pam_syslog(pamh, LOG_NOTICE, "user not authenticated");
			return retval;
		}

		D(("get new password now"));

		lctrl = ctrl;

		if (on(UNIX_USE_AUTHTOK, lctrl)) {
			set(UNIX_USE_FIRST_PASS, lctrl);
		}
		retry = 0;
		retval = PAM_AUTHTOK_ERR;
		while ((retval != PAM_SUCCESS) && (retry++ < MAX_PASSWD_TRIES)) {
			/*
			 * use_authtok is to force the use of a previously entered
			 * password -- needed for pluggable password strength checking
			 */

			retval = _unix_read_password(pamh, lctrl
						     ,NULL
					     ,_("Enter new UNIX password: "******"Retype new UNIX password: "******"password - new password not obtained");
				}
				pass_old = NULL;	/* tidy up */
				return retval;
			}
			D(("returned to _unix_chauthtok"));

			/*
			 * At this point we know who the user is and what they
			 * propose as their new password. Verify that the new
			 * password is acceptable.
			 */

			if (*(const char *)pass_new == '\0') {	/* "\0" password = NULL */
				pass_new = NULL;
			}
			retval = _pam_unix_approve_pass(pamh, ctrl, pass_old,
			                                pass_new, pass_min_len);

			if (retval != PAM_SUCCESS && off(UNIX_NOT_SET_PASS, ctrl)) {
				pam_set_item(pamh, PAM_AUTHTOK, NULL);
			}
		}

		if (retval != PAM_SUCCESS) {
			pam_syslog(pamh, LOG_NOTICE,
			         "new password not acceptable");
			pass_new = pass_old = NULL;	/* tidy up */
			return retval;
		}
		if (lock_pwdf() != PAM_SUCCESS) {
			return PAM_AUTHTOK_LOCK_BUSY;
		}

		if (pass_old) {
			retval = _unix_verify_password(pamh, user, pass_old, ctrl);
			if (retval != PAM_SUCCESS) {
				pam_syslog(pamh, LOG_NOTICE, "user password changed by another process");
				unlock_pwdf();
				return retval;
			}
		}

		retval = _unix_verify_shadow(pamh, user, ctrl);
		if (retval != PAM_SUCCESS) {
			pam_syslog(pamh, LOG_NOTICE, "user shadow entry expired");
			unlock_pwdf();
			return retval;
		}

		retval = _pam_unix_approve_pass(pamh, ctrl, pass_old, pass_new,
		                                pass_min_len);
		if (retval != PAM_SUCCESS) {
			pam_syslog(pamh, LOG_NOTICE,
			         "new password not acceptable 2");
			pass_new = pass_old = NULL;	/* tidy up */
			unlock_pwdf();
			return retval;
		}

		/*
		 * By reaching here we have approved the passwords and must now
		 * rebuild the password database file.
		 */

		/*
		 * First we encrypt the new password.
		 */

		tpass = create_password_hash(pamh, pass_new, ctrl, rounds);
		if (tpass == NULL) {
			pam_syslog(pamh, LOG_CRIT,
				"out of memory for password");
			pass_new = pass_old = NULL;	/* tidy up */
			unlock_pwdf();
			return PAM_BUF_ERR;
		}

		D(("password processed"));

		/* update the password database(s) -- race conditions..? */

		retval = _do_setpass(pamh, user, pass_old, tpass, ctrl,
		                     remember);
	        /* _do_setpass has called unlock_pwdf for us */

		_pam_delete(tpass);
		pass_old = pass_new = NULL;
	} else {		/* something has broken with the module */
		pam_syslog(pamh, LOG_ALERT,
		         "password received unknown request");
		retval = PAM_ABORT;
	}

	D(("retval was %d", retval));

	return retval;
}
コード例 #20
0
ファイル: pam-acct.c プロジェクト: borland667/pbis
/*
 * This is where we check if the password expired.
 * If the password is correct, but has expired, we return
 * PAM_NEW_AUTHTOK_REQD instead of PAM_SUCCESS
 */
int
pam_sm_acct_mgmt(
	pam_handle_t* pamh,
	int           flags,
	int           argc,
	const char**  argv
	)
{
    DWORD dwError = 0;
    PPAMCONTEXT pPamContext = NULL;
    HANDLE hLsaConnection = (HANDLE)NULL;
    PLSA_USER_INFO_2 pUserInfo = NULL;
    DWORD dwUserInfoLevel = 2;
    PSTR  pszLoginId = NULL;
    PLSA_PAM_CONFIG pConfig = NULL;
    int iPamError = 0;
    PSTR pszExpireDone;

    LSA_LOG_PAM_DEBUG("pam_sm_acct_mgmt::begin");

    dwError = LsaPamGetConfig(&pConfig);
    BAIL_ON_LSA_ERROR(dwError);

    LsaPamSetLogLevel(pConfig->dwLogLevel);

    dwError = LsaPamGetContext(
                    pamh,
                    flags,
                    argc,
                    argv,
                    &pPamContext);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaPamGetLoginId(
                    pamh,
                    pPamContext,
                    &pszLoginId,
                    TRUE);
    BAIL_ON_LSA_ERROR(dwError);

    if (LsaShouldIgnoreUser(pszLoginId))
    {
        LSA_LOG_PAM_DEBUG("By passing lsassd for local account");
        dwError = LW_ERROR_NOT_HANDLED;
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = LsaOpenServer(&hLsaConnection);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaCheckUserInList(
                    hLsaConnection,
                    pszLoginId,
                    NULL);
    if (dwError && dwError != LW_ERROR_NO_SUCH_USER)
    {
        if (dwError == LW_ERROR_NO_SUCH_USER)
        {
            BAIL_ON_LSA_ERROR(dwError);
        }
        LSA_LOG_PAM_ERROR("User %s is denied access because they are not in the 'require membership of' list",
                          LSA_SAFE_LOG_STRING(pszLoginId));
        if (!LW_IS_NULL_OR_EMPTY_STR(pConfig->pszAccessDeniedMessage))
        {
            LsaPamConverse(pamh,
                           pConfig->pszAccessDeniedMessage,
                           PAM_TEXT_INFO,
                           NULL);
        }
    }
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaValidateUser(
                    hLsaConnection,
                    pszLoginId,
                    NULL);
    if (dwError == LW_ERROR_PASSWORD_EXPIRED)
    {
        dwError = 0;
        pPamContext->bPasswordExpired = TRUE;
    }
    BAIL_ON_LSA_ERROR(dwError);

    if (pPamContext->bPasswordExpired)
    {
        // If during pam_sm_authenticate,
        // we detected that the password expired,
        // we handle it here
        if (!pPamContext->bPasswordMessageShown)
        {
            LsaPamConverse(
                pamh,
                "Your password has expired",
                PAM_ERROR_MSG,
                NULL);
            pPamContext->bPasswordMessageShown = TRUE;
        }
        dwError = LW_ERROR_PASSWORD_EXPIRED;
        BAIL_ON_LSA_ERROR(dwError);
    }

    iPamError = pam_get_data(
        pamh,
        PAM_LSASS_EXPIRE_WARNING_DONE,
        (PAM_GET_DATA_TYPE)&pszExpireDone);
    if (iPamError == PAM_NO_MODULE_DATA)
    {
        dwError = LsaFindUserByName(
                        hLsaConnection,
                        pszLoginId,
                        dwUserInfoLevel,
                        (PVOID*)&pUserInfo);
        BAIL_ON_LSA_ERROR(dwError);

        if (pUserInfo->bPromptPasswordChange == TRUE &&
            pUserInfo->bPasswordExpired == FALSE && 
            pUserInfo->bPasswordNeverExpires == FALSE) {

            CHAR szMessage[512];

            switch (pUserInfo->dwDaysToPasswordExpiry)
            {
                case 0:
                    sprintf(szMessage, "Your password will expire today\n");
                    break;
                case 1:
                    sprintf(szMessage, "Your password will expire in 1 day\n");
                    break;
                default:
                    sprintf(szMessage, "Your password will expire in %u days\n",
                           pUserInfo->dwDaysToPasswordExpiry);
                    break;
            }
            LsaPamConverse(pamh, szMessage, PAM_TEXT_INFO, NULL);
        }

        dwError = LsaPamSetDataString(
            pamh,
            PAM_LSASS_EXPIRE_WARNING_DONE,
            "TRUE");
        BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:

    if (pUserInfo) {
        LsaFreeUserInfo(dwUserInfoLevel, (PVOID)pUserInfo);
    }

    if (hLsaConnection != (HANDLE)NULL)
    {
        LsaCloseServer(hLsaConnection);
    }

    if (pConfig)
    {
        LsaPamFreeConfig(pConfig);
    }

    LW_SAFE_FREE_STRING(pszLoginId);

    LSA_LOG_PAM_DEBUG("pam_sm_acct_mgmt::end");

    return LsaPamOpenPamFilterAcctMgmt(
                                LsaPamMapErrorCode(dwError, pPamContext));

error:

    if (dwError == LW_ERROR_NO_SUCH_USER || dwError == LW_ERROR_NOT_HANDLED)
    {
        LSA_LOG_PAM_WARNING("pam_sm_acct_mgmt failed [login:%s][error code:%u]",
                          LSA_SAFE_LOG_STRING(pszLoginId),
                          dwError);
    }
    else
    {
        LSA_LOG_PAM_ERROR("pam_sm_acct_mgmt failed [login:%s][error code:%u]",
                          LSA_SAFE_LOG_STRING(pszLoginId),
                          dwError);
        if (pszLoginId && !strcmp(pszLoginId, "root"))
        {
            dwError = LW_ERROR_NO_SUCH_USER;
            LSA_LOG_PAM_ERROR("Converting error to %u for root", dwError);
        }
    }

    goto cleanup;
}
コード例 #21
0
ファイル: pam-session.c プロジェクト: borland667/pbis
int
pam_sm_open_session(
    pam_handle_t* pamh,
    int           flags,
    int           argc,
    const char**  argv
    )
{
    DWORD dwError = 0;
    PPAMCONTEXT pPamContext = NULL;
    HANDLE hLsaConnection = (HANDLE)NULL;
    PSTR pszLoginId = NULL;
    PLSA_PAM_CONFIG pConfig = NULL;

#ifdef HAVE_PAM_PUTENV
    PSTR pszSmartCardReader = NULL;
    PSTR pszSmartCardReaderEnv = NULL;
#endif /* HAVE_PAM_PUTENV */

    LSA_LOG_PAM_DEBUG("pam_sm_open_session::begin");

    dwError = LsaPamGetConfig(&pConfig);
    BAIL_ON_LSA_ERROR(dwError);

    LsaPamSetLogLevel(pConfig->dwLogLevel);

    dwError = LsaPamGetContext(
                    pamh,
                    flags,
                    argc,
                    argv,
                    &pPamContext);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaPamGetLoginId(
                    pamh,
                    pPamContext,
                    &pszLoginId,
                    TRUE);
    BAIL_ON_LSA_ERROR(dwError);

#ifdef HAVE_PAM_PUTENV
    dwError = pam_get_data(
        pamh,
        PAM_LSASS_SMART_CARD_READER,
        (PAM_GET_DATA_TYPE)&pszSmartCardReader);
    /* pszSmartCardReader will be freed when the module is closed. */
    if (dwError == PAM_SUCCESS && pszSmartCardReader != NULL)
    {
        dwError = LwAllocateStringPrintf(
            &pszSmartCardReaderEnv,
            "LW_SMART_CARD_READER=%s",
            pszSmartCardReader);
        BAIL_ON_LSA_ERROR(dwError);

        dwError = pam_putenv(
            pamh,
            pszSmartCardReaderEnv);
        BAIL_ON_LSA_ERROR(dwError);
    }
#endif /* HAVE_PAM_PUTENV */

    if (LsaShouldIgnoreUser(pszLoginId))
    {
        LSA_LOG_PAM_DEBUG("By passing lsassd for local account");
        dwError = LW_ERROR_NOT_HANDLED;
        BAIL_ON_LSA_ERROR(dwError);
    }

    dwError = LsaOpenServer(&hLsaConnection);
    BAIL_ON_LSA_ERROR(dwError);

    dwError = LsaOpenSession(
                    hLsaConnection,
                    pszLoginId);
    BAIL_ON_LSA_ERROR(dwError);


    if (pPamContext &&
        pConfig->bLsaPamDisplayMOTD)
    {
        dwError = LsaPamDisplayMOTD(
                        pamh,
                        pPamContext);
        BAIL_ON_LSA_ERROR(dwError);
    }

    if (pPamContext &&
        pPamContext->bOnlineLogon)
    {
        dwError = LsaPamNotifyUserLogon(
                        pszLoginId);
        if (dwError == LW_ERROR_LOAD_LIBRARY_FAILED ||
            dwError == LW_ERROR_LOOKUP_SYMBOL_FAILED )
        {
            dwError = 0;
        }
        BAIL_ON_LSA_ERROR(dwError);
    }

cleanup:

    if (hLsaConnection != (HANDLE)NULL) {
        LsaCloseServer(hLsaConnection);
    }

    if (pConfig)
    {
        LsaPamFreeConfig(pConfig);
    }

    LW_SAFE_FREE_STRING(pszLoginId);

#ifdef HAVE_PAM_PUTENV
    LW_SAFE_FREE_STRING(pszSmartCardReaderEnv);
#endif /* HAVE_PAM_PUTENV */

    LSA_LOG_PAM_DEBUG("pam_sm_open_session::end");

    return LsaPamOpenPamFilterOpenSession(
                            LsaPamMapErrorCode(dwError, pPamContext));

error:

    if ((dwError == LW_ERROR_NO_SUCH_USER) || (dwError == LW_ERROR_NOT_HANDLED))
    {
        LSA_LOG_PAM_WARNING("pam_sm_open_session failed [login:%s][error code: %u]", 
                            LSA_SAFE_LOG_STRING(pszLoginId),
                            dwError);
    }
    else
    {
        LSA_LOG_PAM_ERROR("pam_sm_open_session failed [login:%s][error code: %u]", 
                          LSA_SAFE_LOG_STRING(pszLoginId),
                          dwError);
    }

    goto cleanup;
}
コード例 #22
0
int
od_record_create(pam_handle_t *pamh, ODRecordRef *record, CFStringRef cfUser)
{
	int retval = PAM_SERVICE_ERR;
	const int attr_num = 5;

	ODNodeRef cfNode = NULL;
	CFErrorRef cferror = NULL;
	CFArrayRef attrs = NULL;
	CFTypeRef cfVals[attr_num];

	if (NULL == record || NULL == cfUser) {
		openpam_log(PAM_LOG_DEBUG, "NULL argument passed");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

#ifdef OPENDIRECTORY_CACHE
#define CFRECORDNAME_CACHE "CFRecordName"
#define CFRECORDNAME_NAME CFSTR("name")
#define CFRECORDNAME_RECORD CFSTR("record")

	CFDictionaryRef cfdict;
	CFStringRef cachedUser;

	if (pam_get_data(pamh, CFRECORDNAME_CACHE, (void *)&cfdict) == PAM_SUCCESS &&
	    (CFGetTypeID(cfdict) == CFDictionaryGetTypeID()) &&
	    (cachedUser = CFDictionaryGetValue(cfdict, CFRECORDNAME_NAME)) != NULL &&
	    CFGetTypeID(cachedUser) == CFStringGetTypeID() &&
	    CFStringCompare(cfUser, cachedUser, 0) == kCFCompareEqualTo &&
	    (*record = (ODRecordRef)CFDictionaryGetValue(cfdict, CFRECORDNAME_RECORD)) != NULL)
	{
		CFRetain(*record);
		return PAM_SUCCESS;
	}
#endif /* OPENDIRECTORY_CACHE */

	int current_iterations = 0;

	cfNode = ODNodeCreateWithNodeType(kCFAllocatorDefault,
					  kODSessionDefault,
					  eDSAuthenticationSearchNodeName,
					  &cferror);
	if (NULL == cfNode || NULL != cferror) {
		openpam_log(PAM_LOG_ERROR, "ODNodeCreateWithNodeType failed.");
		retval = PAM_SERVICE_ERR;
		goto cleanup;
	}

	cfVals[0] = kODAttributeTypeAuthenticationAuthority;
	cfVals[1] = kODAttributeTypeHomeDirectory;
	cfVals[2] = kODAttributeTypeNFSHomeDirectory;
	cfVals[3] = kODAttributeTypeUserShell;
	cfVals[4] = kODAttributeTypeUniqueID;
	attrs = CFArrayCreate(kCFAllocatorDefault, cfVals, (CFIndex)attr_num, &kCFTypeArrayCallBacks);
	if (NULL == attrs) {
		openpam_log(PAM_LOG_DEBUG, "CFArrayCreate() failed");
		retval = PAM_BUF_ERR;
		goto cleanup;
	}

	retval = PAM_SERVICE_ERR;
	while (current_iterations <= kMaxIterationCount) {
		CFIndex unreachable_count = 0;
		CFArrayRef unreachable_nodes = ODNodeCopyUnreachableSubnodeNames(cfNode, NULL);
		if (unreachable_nodes) {
			unreachable_count = CFArrayGetCount(unreachable_nodes);
			CFRelease(unreachable_nodes);
			openpam_log(PAM_LOG_DEBUG, "%lu OD nodes unreachable.", unreachable_count);
		}

		*record = ODNodeCopyRecord(cfNode, kODRecordTypeUsers, cfUser, attrs, &cferror);
		if (*record)
			break;
		if (0 == unreachable_count)
			break;

		openpam_log(PAM_LOG_DEBUG, "Waiting %d seconds for nodes to become reachable", kWaitSeconds);
		sleep(kWaitSeconds);
		++current_iterations;
	}

	if (*record) {
#ifdef OPENDIRECTORY_CACHE
		const void *keys[] = { CFRECORDNAME_NAME, CFRECORDNAME_RECORD };
		const void *values[] = { cfUser, *record };
		CFDictionaryRef dict;
		
		dict = CFDictionaryCreate(NULL, keys, values, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
		if (dict)
			pam_set_data(pamh, CFRECORDNAME_CACHE, (void *)dict, cleanup_cache);
#endif /* OPENDIRECTORY_CACHE */
		retval = PAM_SUCCESS;
	} else {
		retval = PAM_USER_UNKNOWN;
	}

	if (current_iterations > 0) {
		char *wt = NULL, *found = NULL;
		int retval2;

		if (*record)
			found = "failure";
		else
			found = "success";

		retval2 = asprintf(&wt, "%d", kWaitSeconds * current_iterations);
		if (-1 == retval2) {
			openpam_log(PAM_LOG_DEBUG, "Failed to convert current wait time to string.");
			retval = PAM_BUF_ERR;
			goto cleanup;
		}


		aslmsg m = asl_new(ASL_TYPE_MSG);
		asl_set(m, "com.apple.message.domain", "com.apple.pam_modules.odAvailableWaitTime" );
		asl_set(m, "com.apple.message.signature", "wait_time");
		asl_set(m, "com.apple.message.value", wt);
		asl_set(m, "com.apple.message.result", found);
		asl_log(NULL, m, ASL_LEVEL_NOTICE, "OD nodes online delay: %ss. User record lookup: %s.", wt, found);
		asl_free(m);
		free(wt);
	}

cleanup:
	if (NULL != attrs) {
		CFRelease(attrs);
	}

	if (NULL != cferror) {
		CFRelease(cferror);
	}

	if (NULL != cfNode) {
		CFRelease(cfNode);
	}

	if (PAM_SUCCESS != retval) {
		openpam_log(PAM_LOG_ERROR, "failed: %d", retval);
		if (NULL != *record) {
			CFRelease(*record);
			*record = NULL;
		}
	}

	return retval;
}
コード例 #23
0
ファイル: dce_setcred.c プロジェクト: juddy/edcde
/*
 * pam_sm_setcred
 */
int
pam_sm_setcred(
	pam_handle_t *pamh,
	int   flags,
	int	argc,
	const char **argv)
{
	int			debug = 0;
	int			warn = 1;
	int			i;
	dce_module_data_t	*dsd;
	error_status_t		st;
	int			err;

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

	if (flags & PAM_SILENT) warn = 0;

	if (debug)
		syslog(LOG_DEBUG, "DCE pam_setcred");

	if (pam_get_data(pamh, DCE_DATA, (void**)&dsd) != PAM_SUCCESS ||
		dsd == NULL) {
		if (flags & PAM_DELETE_CRED) {
			sec_login_handle_t context;

			/* attempt to get current context and purge */
			sec_login_get_current_context(&context, &st);
			if (st == error_status_ok) {
				sec_login_purge_context(&context, &st);
			}
			return (st == error_status_ok ? PAM_SUCCESS :
					PAM_CRED_UNAVAIL);
		}

		if (warn) do_cred_warn(pamh);
		return (PAM_IGNORE); /* since pam_auth was never called */
	}

	if (dsd->auth_status != PAM_SUCCESS)
		return (dsd->auth_status);

	if (flags & PAM_DELETE_CRED) {
		(void) sec_login_purge_context(dsd->login_context, &st);

		if (debug) {
			dce_error_string_t text;

			syslog(LOG_DEBUG,
				"PAM: DCE sec_login_purge_context: %s",
				get_dce_error_message(st, text));
		}

	} else {
		if (dsd->auth_src == sec_login_auth_src_local) {
			/* we can't set_context on locally authenticated */
			/* contexts */
			st = sec_login_s_auth_local;
		} else {
			(void) sec_login_set_context(dsd->login_context, &st);
		}

		if (debug) {
			dce_error_string_t text;

			syslog(LOG_DEBUG, "PAM: DCE sec_login_set_context: %s",
				get_dce_error_message(st, text));
		}
	}

	/* might want an option to return success even if set_context failed */

	if (st == error_status_ok) {
		return (PAM_SUCCESS);
	} else {
		if (warn) do_cred_warn(pamh);

		if (debug) syslog(LOG_DEBUG,
				"Can't set user login context");
		return (PAM_CRED_ERR);
	}
}
コード例 #24
0
ファイル: krb5_acct_mgmt.c プロジェクト: apprisi/illumos-gate
/*
 * pam_krb5 acct_mgmt
 *
 * we do
 *    - check if pw expired (flag set in auth)
 *    - warn user if pw is set to expire
 *
 * notes
 *    - we require the auth module to have already run (sets module data)
 *    - we don't worry about an expired princ cuz if that's the case,
 *      auth would have failed
 */
int
pam_sm_acct_mgmt(
	pam_handle_t *pamh,
	int	flags,
	int	argc,
	const char **argv)

{
	char *user = NULL;
	char *userdata = NULL;
	int err;
	int i;
	krb5_module_data_t *kmd = NULL;
	char    messages[PAM_MAX_NUM_MSG][PAM_MAX_MSG_SIZE];
	int debug = 0;  /* pam.conf entry option */
	int nowarn = 0; /* pam.conf entry option, no expire warnings */
	pam_repository_t	*rep_data = NULL;

	for (i = 0; i < argc; i++) {
		if (strcasecmp(argv[i], "debug") == 0)
			debug = 1;
		else if (strcasecmp(argv[i], "nowarn") == 0) {
			nowarn = 1;
			flags = flags | PAM_SILENT;
		} else {
			__pam_log(LOG_AUTH | LOG_ERR,
			    "PAM-KRB5 (acct): illegal option %s",
			    argv[i]);
		}
	}

	if (debug)
		__pam_log(LOG_AUTH | LOG_DEBUG,
		    "PAM-KRB5 (acct): debug=%d, nowarn=%d",
		    debug, nowarn);

	(void) pam_get_item(pamh, PAM_REPOSITORY, (void **)&rep_data);

	if (rep_data != NULL) {
		/*
		 * If the repository is not ours,
		 * return PAM_IGNORE.
		 */
		if (strcmp(rep_data->type, KRB5_REPOSITORY_NAME) != 0) {
			if (debug)
				__pam_log(LOG_AUTH | LOG_DEBUG,
					"PAM-KRB5 (acct): wrong"
					"repository found (%s), returning "
					"PAM_IGNORE", rep_data->type);
			return (PAM_IGNORE);
		}
	}


	/* get user name */
	(void) pam_get_item(pamh, PAM_USER, (void **) &user);

	if (user == NULL || *user == '\0') {
		err = PAM_USER_UNKNOWN;
		goto out;
	}

	/* get pam_krb5_migrate specific data */
	err = pam_get_data(pamh, KRB5_AUTOMIGRATE_DATA,
					(const void **)&userdata);
	if (err != PAM_SUCCESS) {
		if (debug)
			__pam_log(LOG_AUTH | LOG_DEBUG, "PAM-KRB5 (acct): "
				"no module data for KRB5_AUTOMIGRATE_DATA");
	} else {
		/*
		 * We try and reauthenticate, since this user has a
		 * newly created krb5 principal via the pam_krb5_migrate
		 * auth module. That way, this new user will have fresh
		 * creds (assuming pam_sm_authenticate() succeeds).
		 */
		if (strcmp(user, userdata) == 0)
			(void) pam_sm_authenticate(pamh, flags, argc,
					(const char **)argv);
		else
			if (debug)
				__pam_log(LOG_AUTH | LOG_DEBUG,
				"PAM-KRB5 (acct): PAM_USER %s"
				"does not match user %s from pam_get_data()",
				user, (char *)userdata);
	}

	/* get krb5 module data  */
	if ((err = pam_get_data(pamh, KRB5_DATA, (const void **)&kmd))
	    != PAM_SUCCESS) {
		if (err == PAM_NO_MODULE_DATA) {
			/*
			 * pam_auth never called (possible config
			 * error; no pam_krb5 auth entry in pam.conf),
			 */
			if (debug) {
				__pam_log(LOG_AUTH | LOG_DEBUG,
				    "PAM-KRB5 (acct): no module data");
			}
			err = PAM_IGNORE;
			goto out;
		} else {
			__pam_log(LOG_AUTH | LOG_ERR,
				    "PAM-KRB5 (acct): get module"
				    " data failed: err=%d",
			    err);
		}
		goto out;
	}

	debug = debug || kmd->debug;

	/*
	 * auth mod set status to ignore, most likely cuz root key is
	 * in keytab, so skip other checks and return ignore
	 */
	if (kmd->auth_status == PAM_IGNORE) {
		if (debug)
			__pam_log(LOG_AUTH | LOG_DEBUG,
			    "PAM-KRB5 (acct): kmd auth_status is IGNORE");
		err = PAM_IGNORE;
		goto out;
	}

	/*
	 * If there is no Kerberos related user and there is authentication
	 * data, this means that while the user has successfully passed
	 * authentication, Kerberos is not the account authority because there
	 * is no valid Kerberos principal.  PAM_IGNORE is returned since
	 * Kerberos is not authoritative for this user.  Other modules in the
	 * account stack will need to determine the success or failure for this
	 * user.
	 */
	if (kmd->auth_status == PAM_USER_UNKNOWN) {
		if (debug)
			syslog(LOG_DEBUG,
			    "PAM-KRB5 (acct): kmd auth_status is USER UNKNOWN");
		err = PAM_IGNORE;
		goto out;
	}

	/*
	 * age_status will be set to PAM_NEW_AUTHTOK_REQD in pam_krb5's
	 * 'auth' if the user's key/pw has expired and needs to be changed
	 */
	if (kmd->age_status == PAM_NEW_AUTHTOK_REQD) {
		if (!nowarn) {
			(void) snprintf(messages[0], sizeof (messages[0]),
				dgettext(TEXT_DOMAIN,
				"Your Kerberos password has expired.\n"));
			(void) __pam_display_msg(pamh, PAM_TEXT_INFO,
					1, messages, NULL);
		}
		err = PAM_NEW_AUTHTOK_REQD;
		goto out;
	}

	if (kmd->auth_status == PAM_SUCCESS && !(flags & PAM_SILENT) &&
	    !nowarn && kmd->password) {
		/* if we fail, let it slide, it's only a warning brah */
		(void) exp_warn(pamh, user, kmd, debug);
	}

	/*
	 * If Kerberos is treated as optional in the PAM stack, it is possible
	 * that there is a KRB5_DATA item and a non-Kerberos account authority.
	 * In that case, PAM_IGNORE is returned.
	 */
	err = kmd->auth_status != PAM_SUCCESS ? PAM_IGNORE : kmd->auth_status;

out:
	if (debug)
		__pam_log(LOG_AUTH | LOG_DEBUG,
		    "PAM-KRB5 (acct): end: %s", pam_strerror(pamh, err));

	return (err);
}
コード例 #25
0
int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
                     int argc, const char **argv)
{
    unsigned int ctrl;
    int retval;

    extern BOOL in_client;

    SAM_ACCOUNT *sampass = NULL;
    void (*oldsig_handler)(int);
    const char *user;
    char *pass_old;
    char *pass_new;

    NTSTATUS nt_status;

    /* Samba initialization. */
    setup_logging( "pam_smbpass", False );
    in_client = True;

    ctrl = set_ctrl(flags, argc, argv);

    /*
     * First get the name of a user.  No need to do anything if we can't
     * determine this.
     */

    retval = pam_get_user( pamh, &user, "Username: "******"password: could not identify user" );
        }
        return retval;
    }
    if (on( SMB_DEBUG, ctrl )) {
        _log_err( LOG_DEBUG, "username [%s] obtained", user );
    }

    /* Getting into places that might use LDAP -- protect the app
       from a SIGPIPE it's not expecting */
    oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN);

    if (!initialize_password_db(True)) {
        _log_err( LOG_ALERT, "Cannot access samba password database" );
        CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
        return PAM_AUTHINFO_UNAVAIL;
    }

    /* obtain user record */
    if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
        CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
        return nt_status_to_pam(nt_status);
    }

    if (!pdb_getsampwnam(sampass,user)) {
        _log_err( LOG_ALERT, "Failed to find entry for user %s.", user );
        CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
        return PAM_USER_UNKNOWN;
    }

    if (flags & PAM_PRELIM_CHECK) {
        /*
         * obtain and verify the current password (OLDAUTHTOK) for
         * the user.
         */

        char *Announce;

        if (_smb_blankpasswd( ctrl, sampass )) {

            pdb_free_sam(&sampass);
            CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
            return PAM_SUCCESS;
        }

	/* Password change by root, or for an expired token, doesn't
           require authentication.  Is this a good choice? */
        if (getuid() != 0 && !(flags & PAM_CHANGE_EXPIRED_AUTHTOK)) {

            /* tell user what is happening */
#define greeting "Changing password for "
            Announce = (char *) malloc(sizeof(greeting)+strlen(user));
            if (Announce == NULL) {
                _log_err(LOG_CRIT, "password: out of memory");
                pdb_free_sam(&sampass);
                CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
                return PAM_BUF_ERR;
            }
            strncpy( Announce, greeting, sizeof(greeting) );
            strncpy( Announce+sizeof(greeting)-1, user, strlen(user)+1 );
#undef greeting

            set( SMB__OLD_PASSWD, ctrl );
            retval = _smb_read_password( pamh, ctrl, Announce, "Current SMB password: "******"password - (old) token not obtained" );
                pdb_free_sam(&sampass);
                CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
                return retval;
            }

            /* verify that this is the password for this user */

            retval = _smb_verify_password( pamh, sampass, pass_old, ctrl );

        } else {
	    pass_old = NULL;
            retval = PAM_SUCCESS;           /* root doesn't have to */
        }

        pass_old = NULL;
        pdb_free_sam(&sampass);
        CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
        return retval;

    } else if (flags & PAM_UPDATE_AUTHTOK) {

        /*
         * obtain the proposed password
         */

        /*
         * get the old token back. NULL was ok only if root [at this
         * point we assume that this has already been enforced on a
         * previous call to this function].
         */

        if (off( SMB_NOT_SET_PASS, ctrl )) {
            retval = pam_get_item( pamh, PAM_OLDAUTHTOK,
                                   (const void **)&pass_old );
        } else {
            retval = pam_get_data( pamh, _SMB_OLD_AUTHTOK,
                                   (const void **)&pass_old );
            if (retval == PAM_NO_MODULE_DATA) {
		pass_old = NULL;
                retval = PAM_SUCCESS;
            }
        }

        if (retval != PAM_SUCCESS) {
            _log_err( LOG_NOTICE, "password: user not authenticated" );
            pdb_free_sam(&sampass);
            CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
            return retval;
        }

        /*
         * use_authtok is to force the use of a previously entered
         * password -- needed for pluggable password strength checking
	 * or other module stacking
         */

        if (on( SMB_USE_AUTHTOK, ctrl )) {
            set( SMB_USE_FIRST_PASS, ctrl );
        }

        retval = _smb_read_password( pamh, ctrl
                                      , NULL
                                      , "Enter new SMB password: "******"Retype new SMB password: "******"password: new password not obtained" );
            }
            pass_old = NULL;                               /* tidy up */
            pdb_free_sam(&sampass);
            CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
            return retval;
        }

        /*
         * At this point we know who the user is and what they
         * propose as their new password. Verify that the new
         * password is acceptable.
         */ 

        if (pass_new[0] == '\0') {     /* "\0" password = NULL */
            pass_new = NULL;
        }

        retval = _pam_smb_approve_pass(pamh, ctrl, pass_old, pass_new);

        if (retval != PAM_SUCCESS) {
            _log_err(LOG_NOTICE, "new password not acceptable");
            pass_new = pass_old = NULL;               /* tidy up */
            pdb_free_sam(&sampass);
            CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
            return retval;
        }

        /*
         * By reaching here we have approved the passwords and must now
         * rebuild the smb password file.
         */

        /* update the password database */

        retval = smb_update_db(pamh, ctrl, user, pass_new);
        if (retval == PAM_SUCCESS) {
	    uid_t uid;
	    
            /* password updated */
		if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &uid))) {
			_log_err( LOG_NOTICE, "Unable to get uid for user %s",
				pdb_get_username(sampass));
			_log_err( LOG_NOTICE, "password for (%s) changed by (%s/%d)",
				user, uidtoname(getuid()), getuid());
		} else {
			_log_err( LOG_NOTICE, "password for (%s/%d) changed by (%s/%d)",
				user, uid, uidtoname(getuid()), getuid());
		}
	} else {
		_log_err( LOG_ERR, "password change failed for user %s", user);
	}

        pass_old = pass_new = NULL;
	if (sampass) {
		pdb_free_sam(&sampass);
		sampass = NULL;
	}

    } else {            /* something has broken with the library */

        _log_err( LOG_ALERT, "password received unknown request" );
        retval = PAM_ABORT;

    }
    
    if (sampass) {
    	pdb_free_sam(&sampass);
	sampass = NULL;
    }

    pdb_free_sam(&sampass);
    CatchSignal(SIGPIPE, SIGNAL_CAST oldsig_handler);
    return retval;
}
コード例 #26
0
ファイル: pam_local.c プロジェクト: millken/zhuxianB30
/*****************************************************************************
    Func Name: pam_local_session_update
 Date Created: 2009/2/23
       Author: chendong
  Description: 更新本地计费会话信息
        Input: pam_handle_t* pamh  PAM Handle
               sqlite3 *db       数据库句柄
       Output: 无
       Return: 无
      Caution:
-----------------------------------------------------------------------------
   Modification History
   DATE        NAME             DESCRIPTION
-----------------------------------------------------------------------------

******************************************************************************/
static int pam_local_session_update (pam_handle_t * pamh, sqlite3 *db)
{
    time_t now;
    int rc;
    const int *seq = NULL;
    struct pam_ext_item *item = NULL;
	s8 sql[MAX_SQL_STR] = {0};
    unsigned int pkt_in = 0, pkt_out = 0, oct_in = 0, oct_out = 0;
	void *item_tmp = (void *)item;

    /* 获取start的时候保持的序列号 */
    rc = pam_get_data (pamh, PAM_LOCAL_ACCT_SEQ, (const void **)&item_tmp);
	item = (struct pam_ext_item *)item_tmp;
    if (PAM_SUCCESS != rc || NULL == seq)
    {
        return PAM_BUF_ERR;
    }

    /* 获取统计项 */
    rc = pam_get_item (pamh, PAM_EXT_ACCT_INPUT_PACKETS, (const void **)&item_tmp);
	item = (struct pam_ext_item *)item_tmp;
    if (PAM_SUCCESS == rc)
    {
        pkt_in = *(unsigned int *) item->item_value;
    }

    rc = pam_get_item (pamh, PAM_EXT_ACCT_OUTPUT_PACKETS,
                       (const void **)&item_tmp);
	item = (struct pam_ext_item *)item_tmp;
    if (PAM_SUCCESS == rc)
    {
        pkt_out= *(unsigned int *) item->item_value;
    }

    rc = pam_get_item (pamh, PAM_EXT_ACCT_INPUT_OCTETS, (const void **)&item_tmp);
	item = (struct pam_ext_item *)item_tmp;
    if (PAM_SUCCESS == rc)
    {
        oct_in = *(unsigned int *) item->item_value;
    }

    rc = pam_get_item (pamh, PAM_EXT_ACCT_OUTPUT_OCTETS, (const void **)&item_tmp);
	item = (struct pam_ext_item *)item_tmp;
    if (PAM_SUCCESS == rc)
    {
        oct_out = *(unsigned int *) item->item_value;
    }

    /* 获取当前时间,将下线时间更新为当前时间 */
    now = time (NULL);

    /* 更新计费表项 */
	sprintf((char *)sql, "update tb_pam_account set logout_time = %ld, input_packets = %d, output_packets = %d, input_octets = %d, output_octets = %d where sequence = %d;", now, pkt_in, pkt_out, oct_in, oct_out, *seq);
	rc= (int)sqlite3_exec_ex(db, sql);

    if (0 != rc)
    {
        pam_local_logger ("dba error %d", rc);
        return PAM_SYSTEM_ERR;
    }

    return PAM_SUCCESS;
}
コード例 #27
0
ファイル: afs_setcred.c プロジェクト: sanchit-matta/openafs
extern int
pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv)
{
    int retcode = PAM_SUCCESS;
    int errcode = PAM_SUCCESS;
    int origmask;
    int logmask = LOG_UPTO(LOG_INFO);
    int nowarn = 0;
    int use_first_pass = 1;	/* use the password passed in by auth */
    int try_first_pass = 0;
    int ignore_uid = 0;
    uid_t ignore_uid_id = 0;
    int refresh_token = 0;
    int set_expires = 0;	/* the default is to not to set the env variable */
    int use_klog = 0;
    int i;
    PAM_CONST struct pam_conv *pam_convp = NULL;
    char my_password_buf[256];
    char *cell_ptr = NULL;
    char sbuffer[100];
    char *torch_password = NULL;
    int auth_ok = 0;
    PAM_CONST char *user = NULL;
    const char *password = NULL;
    int password_expires = -1;
    char *reason = NULL;
    struct passwd *upwd = NULL;
#if !(defined(AFS_LINUX20_ENV) || defined(AFS_FBSD_ENV) || defined(AFS_DFBSD_ENV) || defined(AFS_NBSD_ENV))
    char upwd_buf[2048];       /* size is a guess. */
    struct passwd unix_pwd;
#endif

#ifndef AFS_SUN5_ENV
    openlog(pam_afs_ident, LOG_CONS, LOG_AUTH);
#endif
    origmask = setlogmask(logmask);

    /*
     * Parse the user options.  Log an error for any unknown options.
     */
    for (i = 0; i < argc; i++) {
	if (strcasecmp(argv[i], "debug") == 0) {
	    logmask |= LOG_MASK(LOG_DEBUG);
	    (void)setlogmask(logmask);
	} else if (strcasecmp(argv[i], "nowarn") == 0) {
	    nowarn = 1;
	} else if (strcasecmp(argv[i], "use_first_pass") == 0) {
	    use_first_pass = 1;	/* practically redundant */
	} else if (strcasecmp(argv[i], "try_first_pass") == 0) {
	    try_first_pass = 1;
	} else if (strcasecmp(argv[i], "ignore_root") == 0) {
	    ignore_uid = 1;
	    ignore_uid_id = 0;
	} else if (strcasecmp(argv[i], "ignore_uid") == 0) {
	    i++;
	    if (i == argc) {
		pam_afs_syslog(LOG_ERR, PAMAFS_IGNOREUID,
			       "ignore_uid missing argument");
		ignore_uid = 0;
	    } else {
		ignore_uid = 1;
		ignore_uid_id = (uid_t) strtol(argv[i], (char **)NULL, 10);
		if (ignore_uid_id > IGNORE_MAX) {
		    ignore_uid = 0;
		    pam_afs_syslog(LOG_ERR, PAMAFS_IGNOREUID, argv[i]);
		}
	    }
	} else if (strcasecmp(argv[i], "cell") == 0) {
	    i++;
	    if (i == argc) {
		pam_afs_syslog(LOG_ERR, PAMAFS_OTHERCELL,
			       "cell missing argument");
	    } else {
		cell_ptr = (char *)argv[i];
		pam_afs_syslog(LOG_INFO, PAMAFS_OTHERCELL, cell_ptr);
	    }
	} else if (strcasecmp(argv[i], "no_unlog") == 0) {
	    ;
	} else if (strcasecmp(argv[i], "refresh_token") == 0) {
	    refresh_token = 1;
	} else if (strcasecmp(argv[i], "set_token") == 0) {
	    ;
	} else if (strcasecmp(argv[i], "dont_fork") == 0) {
	    ;
	} else if (strcasecmp(argv[i], "use_klog") == 0) {
	    use_klog = 1;
	} else if (strcasecmp(argv[i], "setenv_password_expires") == 0) {
	    set_expires = 1;
	} else {
	    pam_afs_syslog(LOG_ERR, PAMAFS_UNKNOWNOPT, argv[i]);
	}
    }

    if (use_first_pass)
	try_first_pass = 0;

    if (logmask & LOG_MASK(LOG_DEBUG))
	pam_afs_syslog(LOG_DEBUG, PAMAFS_OPTIONS, nowarn, use_first_pass,
		       try_first_pass, ignore_uid, ignore_uid_id, 8, 8, 8, 8);
    /* Try to get the user-interaction info, if available. */
    errcode = pam_get_item(pamh, PAM_CONV, (PAM_CONST void **)&pam_convp);
    if (errcode != PAM_SUCCESS) {
	if (logmask & LOG_MASK(LOG_DEBUG))
	    pam_afs_syslog(LOG_DEBUG, PAMAFS_NO_USER_INT);
	pam_convp = NULL;
    }

    /* Who are we trying to authenticate here? */
    if ((errcode =
	 pam_get_user(pamh, (PAM_CONST char **)&user,
		      "AFS username:"******"local" (or via nss, possibly nss_dce) pwent,
     * and its uid==0, and "ignore_root" was given in pam.conf,
     * ignore the user.
     */
    /* enhanced: use "ignore_uid <number>" to specify the largest uid
     * which should be ignored by this module
     */
#if	defined(AFS_HPUX_ENV) || defined(AFS_DARWIN100_ENV) || defined(AFS_SUN5_ENV)
#if     defined(AFS_HPUX110_ENV) || defined(AFS_DARWIN100_ENV) || defined(AFS_SUN5_ENV)
    i = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf), &upwd);
#else /* AFS_HPUX110_ENV */
    i = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf));
    if (i == 0)			/* getpwnam_r success */
	upwd = &unix_pwd;
#endif /* AFS_HPUX110_ENV */
    if (ignore_uid && i == 0 && upwd && upwd->pw_uid <= ignore_uid_id) {
	pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
	RET(PAM_AUTH_ERR);
    }
#else
#if     defined(AFS_LINUX20_ENV) || defined(AFS_FBSD_ENV) || defined(AFS_DFBSD_ENV) || defined(AFS_NBSD_ENV)
    upwd = getpwnam(user);
#else
    upwd = getpwnam_r(user, &unix_pwd, upwd_buf, sizeof(upwd_buf));
#endif
    if (ignore_uid && upwd != NULL && upwd->pw_uid <= ignore_uid_id) {
	pam_afs_syslog(LOG_INFO, PAMAFS_IGNORINGROOT, user);
	RET(PAM_AUTH_ERR);
    }
#endif

    if (flags & PAM_DELETE_CRED) {
	if (logmask & LOG_MASK(LOG_DEBUG))
	    pam_afs_syslog(LOG_DEBUG, PAMAFS_DELCRED, user);

	RET(PAM_SUCCESS);
    } else if (flags & PAM_REINITIALIZE_CRED) {

	if (logmask & LOG_MASK(LOG_DEBUG))
	    pam_afs_syslog(LOG_DEBUG, PAMAFS_REINITCRED, user);
	RET(PAM_SUCCESS);

    } else {			/* flags are PAM_REFRESH_CRED, PAM_ESTABLISH_CRED, unknown */

	if (logmask & LOG_MASK(LOG_DEBUG))
	    pam_afs_syslog(LOG_DEBUG, PAMAFS_ESTABCRED, user);

	errcode = pam_get_data(pamh, pam_afs_lh, (const void **)&password);
	if (errcode != PAM_SUCCESS || password == NULL) {
	    if (use_first_pass) {
		pam_afs_syslog(LOG_ERR, PAMAFS_PASSWD_REQ, user);
		RET(PAM_AUTH_ERR);
	    }
	    password = NULL;	/* In case it isn't already NULL */
	    if (logmask & LOG_MASK(LOG_DEBUG))
		pam_afs_syslog(LOG_DEBUG, PAMAFS_NOFIRSTPASS, user);
	} else if (password[0] == '\0') {
	    /* Actually we *did* get one but it was empty. */
	    /* So don't use it. */
	    password = NULL;
	    if (use_first_pass) {
		pam_afs_syslog(LOG_ERR, PAMAFS_PASSWD_REQ, user);
		RET(PAM_NEW_AUTHTOK_REQD);
	    }
	    if (logmask & LOG_MASK(LOG_DEBUG))
		pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD, user);
	} else {
	    if (logmask & LOG_MASK(LOG_DEBUG))
		pam_afs_syslog(LOG_DEBUG, PAMAFS_GOTPASS, user);
	}
	if (!(use_first_pass || try_first_pass)) {
	    password = NULL;
	}

      try_auth:
	if (password == NULL) {
	    char *prompt_password;

	    if (use_first_pass)
		RET(PAM_AUTH_ERR);	/* shouldn't happen */
	    if (try_first_pass)
		try_first_pass = 0;	/* we come back if try_first_pass==1 below */

	    if (pam_convp == NULL || pam_convp->conv == NULL) {
		pam_afs_syslog(LOG_ERR, PAMAFS_CANNOT_PROMPT);
		RET(PAM_AUTH_ERR);
	    }

	    errcode =
		pam_afs_prompt(pam_convp, &prompt_password, 0, PAMAFS_PWD_PROMPT);
	    if (errcode != PAM_SUCCESS || prompt_password == NULL) {
		pam_afs_syslog(LOG_ERR, PAMAFS_GETPASS_FAILED);
		RET(PAM_AUTH_ERR);
	    }
	    if (prompt_password[0] == '\0') {
		if (logmask & LOG_MASK(LOG_DEBUG))
		    pam_afs_syslog(LOG_DEBUG, PAMAFS_NILPASSWORD);
		RET(PAM_NEW_AUTHTOK_REQD);
	    }
	    /*
	     * We aren't going to free the password later (we will wipe it,
	     * though), because the storage for it if we get it from other
	     * paths may belong to someone else.  Since we do need to free
	     * this storage, copy it to a buffer that won't need to be freed
	     * later, and free this storage now.
	     */

	    strncpy(my_password_buf, prompt_password, sizeof(my_password_buf));
	    my_password_buf[sizeof(my_password_buf) - 1] = '\0';
	    memset(prompt_password, 0, strlen(prompt_password));
	    free(prompt_password);
	    password = torch_password = my_password_buf;
	}
	/*
	 * We only set a PAG here, if we haven't got one before in
	 * pam_sm_authenticate() or if it was destroyed by the application
	 */
	if ((!refresh_token) && (getPAG() == -1)) {
	    if (logmask & LOG_MASK(LOG_DEBUG))
		syslog(LOG_DEBUG, "New PAG created in pam_setcred()");
	    setpag();
#ifdef AFS_KERBEROS_ENV
	    ktc_newpag();
#endif
	}

	if (flags & PAM_REFRESH_CRED) {
	    if (use_klog) {
		auth_ok = !do_klog(user, password, "00:00:01", cell_ptr);
		ktc_ForgetAllTokens();
	    } else {
		if (ka_VerifyUserPassword(KA_USERAUTH_VERSION, (char *)user,	/* kerberos name */
					  NULL,	/* instance */
					  cell_ptr,	/* realm */
					  (char*)password,	/* password */
					  0,	/* spare 2 */
					  &reason	/* error string */
		    )) {
		    pam_afs_syslog(LOG_ERR, PAMAFS_LOGIN_FAILED, user,
				   reason);
		} else {
		    auth_ok = 1;
		}
	    }
	}

	if (flags & PAM_ESTABLISH_CRED) {
	    if (use_klog)
		auth_ok = !do_klog(user, password, NULL, cell_ptr);
	    else {
		if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, (char *)user,	/* kerberos name */
					       NULL,	/* instance */
					       cell_ptr,	/* realm */
					       (char*)password,	/* password */
					       0,	/* default lifetime */
					       &password_expires, 0,	/* spare 2 */
					       &reason	/* error string */
		    )) {
		    pam_afs_syslog(LOG_ERR, PAMAFS_LOGIN_FAILED, user,
				   reason);
		} else {
		    auth_ok = 1;
		}
	    }
	}

	if (!auth_ok && try_first_pass) {
	    password = NULL;
	    goto try_auth;
	}

	/* pam_sm_authenticate should have set this
	 * if (auth_ok && !got_authtok) {
	 *     torch_password = NULL;
	 *     (void) pam_set_item(pamh, PAM_AUTHTOK, password);
	 * }
	 */

	if (auth_ok) {
	    if (set_expires && !use_klog && (password_expires >= 0)) {
		strcpy(sbuffer, "PASSWORD_EXPIRES=");
		strcat(sbuffer, cv2string(&sbuffer[100], password_expires));
		errcode = pam_putenv(pamh, sbuffer);
		if (errcode != PAM_SUCCESS)
		    pam_afs_syslog(LOG_ERR, PAMAFS_PASSEXPFAIL, user);
	    }
#if defined(AFS_KERBEROS_ENV)
	    if (upwd) {
		if (chown(ktc_tkt_string(), upwd->pw_uid, upwd->pw_gid) < 0)
		    pam_afs_syslog(LOG_ERR, PAMAFS_CHOWNKRB, user);
		sprintf(sbuffer, "KRBTKFILE=%s", ktc_tkt_string());
		errcode = pam_putenv(pamh, sbuffer);
		if (errcode != PAM_SUCCESS)
		    pam_afs_syslog(LOG_ERR, PAMAFS_KRBFAIL, user);
	    }
#endif

	    RET(PAM_SUCCESS);
	} else {
	    RET(PAM_CRED_ERR);
	}
    }

  out:
    if (password && torch_password)
	memset(torch_password, 0, strlen(torch_password));
    (void)setlogmask(origmask);
#ifndef AFS_SUN5_ENV
    closelog();
#endif
    return retcode;
}
コード例 #28
0
DWORD
LsaPamGetContext(
    pam_handle_t* pamh, 
    int           flags, 
    int           argc, 
    const char**  argv,
    PPAMCONTEXT*  ppPamContext
    )
{
    DWORD       dwError = 0;
    PPAMCONTEXT pPamContext = NULL;
    BOOLEAN     bFreeContext = FALSE;
    int         iPamError = 0;
    
    LSA_LOG_PAM_DEBUG("LsaPamGetContext::begin");
    
    iPamError = pam_get_data(pamh, MODULE_NAME, (PAM_GET_DATA_TYPE)&pPamContext);
    dwError = LsaPamUnmapErrorCode(iPamError);
    if (dwError)
    {
        if (dwError == LsaPamUnmapErrorCode(PAM_NO_MODULE_DATA))
        {
                dwError = LwAllocateMemory(
                                sizeof(PAMCONTEXT),
                                (PVOID*)&pPamContext);
                BAIL_ON_LSA_ERROR(dwError);

                bFreeContext = TRUE;

                iPamError = pam_set_data(
                                pamh,
                                MODULE_NAME,
                                (PVOID)pPamContext,
                                &LsaPamCleanupContext);
                dwError = LsaPamUnmapErrorCode(iPamError);
                BAIL_ON_LSA_ERROR(dwError);

                bFreeContext = FALSE;
        }
        else
        {
                BAIL_ON_LSA_ERROR(dwError);
        }
    }

    dwError = LsaPamGetLoginId(pamh, pPamContext, NULL, FALSE);
    BAIL_ON_LSA_ERROR(dwError);
    
    dwError = LsaPamGetOptions(
                    pamh,
                    flags,
                    argc,
                    argv,
                    &pPamContext->pamOptions);
    BAIL_ON_LSA_ERROR(dwError);
    
    *ppPamContext = pPamContext;
    
cleanup:

    LSA_LOG_PAM_DEBUG("LsaPamGetContext::end");

    return dwError;

error:

    if (pPamContext && bFreeContext) {
       LsaPamFreeContext(pPamContext);
    }

    *ppPamContext = NULL;
    
    LSA_LOG_PAM_ERROR("LsaPamGetContext failed [error code: %u]", dwError);

    goto cleanup;
}
コード例 #29
0
struct passwd *
pam_modutil_getpwuid(pam_handle_t *pamh, uid_t uid)
{
#ifdef HAVE_GETPWUID_R

    void *buffer=NULL;
    size_t length = PWD_INITIAL_LENGTH;

    do {
	int status;
	void *new_buffer;
	struct passwd *result = NULL;

	new_buffer = realloc(buffer, sizeof(struct passwd) + length);
	if (new_buffer == NULL) {

	    D(("out of memory"));

	    /* no memory for the user - so delete the memory */
	    if (buffer) {
		free(buffer);
	    }
	    return NULL;
	}
	buffer = new_buffer;

	/* make the re-entrant call to get the pwd structure */
        errno = 0;
	status = getpwuid_r(uid, buffer,
			    sizeof(struct passwd) + (char *) buffer,
			    length, &result);
	if (!status && (result == buffer)) {
	    char *data_name;
	    const void *ignore;
	    int i;

	    data_name = malloc(strlen("_pammodutil_getpwuid") + 1 +
			       longlen((long) uid) + 1 + intlen(INT_MAX) + 1);
	    if ((pamh != NULL) && (data_name == NULL)) {
	        D(("was unable to register the data item [%s]",
	           pam_strerror(pamh, status)));
		free(buffer);
		return NULL;
	    }

	    if (pamh != NULL) {
	        for (i = 0; i < INT_MAX; i++) {
	            sprintf(data_name, "_pammodutil_getpwuid_%ld_%d",
			    (long) uid, i);
		    status = PAM_NO_MODULE_DATA;
	            if (pam_get_data(pamh, data_name, &ignore) != PAM_SUCCESS) {
		        status = pam_set_data(pamh, data_name,
					      result, pam_modutil_cleanup);
		    }
		    if (status == PAM_SUCCESS) {
		        break;
		    }
		}
	    } else {
	        status = PAM_SUCCESS;
	    }

	    free(data_name);

	    if (status == PAM_SUCCESS) {
		D(("success"));
		return result;
	    }

	    D(("was unable to register the data item [%s]",
	       pam_strerror(pamh, status)));

	    free(buffer);
	    return NULL;

	} else if (errno != ERANGE && errno != EINTR) {
                /* no sense in repeating the call */
                break;
        }

	length <<= PWD_LENGTH_SHIFT;

    } while (length < PWD_ABSURD_PWD_LENGTH);

    D(("pwd structure took %u bytes or so of memory",
       length+sizeof(struct passwd)));

    free(buffer);
    return NULL;

#else /* ie. ifndef HAVE_GETPWUID_R */

    /*
     * Sorry, there does not appear to be a reentrant version of
     * getpwuid(). So, we use the standard libc function.
     */

    return getpwuid(uid);

#endif /* def HAVE_GETPWUID_R */
}
コード例 #30
0
ファイル: pam_kwallet.c プロジェクト: amaramrahul/pam-kwallet
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, const char **argv)
{
    pam_syslog(pamh, LOG_INFO, "pam_sm_authenticate\n");
    if (get_env(pamh, "PAM_KWALLET_LOGIN") != NULL) {
        pam_syslog(pamh, LOG_INFO, "pam_kwallet: we were already executed");
        return PAM_SUCCESS;
    }

    parseArguments(argc, argv);

    int result;

    //Fetch the user, needed to get user information
    const char *username;
    result = pam_get_user(pamh, &username, NULL);
    if (result != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Couldn't get username %s",
                   pam_strerror(pamh, result));
        return PAM_IGNORE;//Since we are not an essential module, just make pam ignore us
    }

    struct passwd *userInfo;
    userInfo = getpwnam(username);
    if (!userInfo) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Couldn't get user info (passwd) info");
        return PAM_IGNORE;
    }

    const char *password;
    result = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&password);

    if (result != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Couldn't get password %s",
                   pam_strerror(pamh, result));
        return PAM_IGNORE;
    }

    if (!password) {
        pam_syslog(pamh, LOG_NOTICE, "pam_kwallet: Couldn't get password (it is empty)");
        //Asking for the password ourselves
        result = prompt_for_password(pamh);
        if (result != PAM_SUCCESS) {
            pam_syslog(pamh, LOG_ERR, "pam_kwallet: Prompt for password failed %s",
                pam_strerror(pamh, result)
            );
            return PAM_IGNORE;
        }
    }

    //even though we just set it, better check to be 100% sure
    result = pam_get_item(pamh, PAM_AUTHTOK, (const void**)&password);
    if (result != PAM_SUCCESS || !password) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Password is not there even though we set it %s",
                   pam_strerror(pamh, result));
        return PAM_IGNORE;
    }

    char *key = malloc(sizeof(char) * KWALLET_PAM_KEYSIZE);
    if (kwallet_hash(password, userInfo, key) != 0) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Fail into creating the hash");
        return PAM_IGNORE;
    }

    result = pam_set_data(pamh, "kwallet_key", key, NULL);
    if (result != PAM_SUCCESS) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: Impossible to store the hashed password: %s"
            , pam_strerror(pamh, result));
        return PAM_IGNORE;
    }

    //if sm_open_session has already been called (but we did not have password), call it now
    const char *session_bit;
    result = pam_get_data(pamh, "sm_open_session", (const void **)&session_bit);
    if (result == PAM_SUCCESS) {
        pam_syslog(pamh, LOG_ERR, "pam_kwallet: open_session was called before us, calling it now");
        return pam_sm_open_session(pamh, flags, argc, argv);
    }

    //TODO unlock kwallet that is already executed
    return PAM_SUCCESS;
}