コード例 #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
ファイル: verify.c プロジェクト: 2014-class/freerouter
static void
set_krbtkfile(uid_t uid)
{
    snprintf (krbtkfile, sizeof(krbtkfile), "%s%d", TKT_ROOT, (unsigned)uid);
    krb_set_tkt_string (krbtkfile);
    correct_tkfilename = 1;
}
コード例 #3
0
ファイル: kerb4.c プロジェクト: CVi/sudo
int
kerb4_verify(struct passwd *pw, char *pass, sudo_auth *auth)
{
    char tkfile[sizeof(_PATH_SUDO_TIMEDIR) + 4 + MAX_UID_T_LEN];
    char *realm = (char *) auth->data;
    int error;

    /*
     * Set the ticket file to be in sudo sudo timedir so we don't
     * wipe out other (real) kerberos tickets.
     */
    (void) snprintf(tkfile, sizeof(tkfile), "%s/tkt%u",
	_PATH_SUDO_TIMEDIR, (unsigned int) pw->pw_uid);
    (void) krb_set_tkt_string(tkfile);

    /* Convert the password to a ticket given. */
    error = krb_get_pw_in_tkt(pw->pw_name, "", realm, "krbtgt", realm,
	DEFAULT_TKT_LIFE, pass);

    switch (error) {
	case INTK_OK:
	    dest_tkt();			/* we are done with the temp ticket */
	    return AUTH_SUCCESS;
	    break;
	case INTK_BADPW:
	case KDC_PR_UNKNOWN:
	    break;
	default:
	    (void) fprintf(stderr, "Warning: Kerberos error: %s\n",
		krb_err_txt[error]);
    }

    return AUTH_FAILURE;
}
コード例 #4
0
ファイル: rk_lib.c プロジェクト: mit-athena/librkinit
int rkinit(char *host, char *r_krealm, rkinit_info *info, int timeout)
{
    int status;
    int version = 0;
    char phost[MAXHOSTNAMELEN];
    jmp_buf timeout_env;
    struct sigaction osa;
    char origtktfilename[MAXPATHLEN]; /* original ticket file name */
    char tktfilename[MAXPATHLEN]; /* temporary client ticket file */

    BCLEAR(phost);
    BCLEAR(origtktfilename);
    BCLEAR(tktfilename);
    BCLEAR(timeout_env);

    initialize_rkin_error_table();

    status = rki_setup_rpc(host);
    if (status)
	return(status);

    /* The alarm handler longjmps us to here. */
    status = setjmp(timeout_env);
    if (status == 0) {
	strcpy(origtktfilename, tkt_string());
	sprintf(tktfilename, "/tmp/tkt_rkinit.%lu", (unsigned long)getpid());
	krb_set_tkt_string(tktfilename);

	if (timeout)
	    rki_setup_timer(timeout_env, &osa);

	status = rki_choose_version(&version);
	if (status == RKINIT_SUCCESS)
	    status = rki_get_tickets(version, host, r_krealm, info);
    }

    if (timeout)
	rki_restore_timer(&osa);

    dest_tkt();
    krb_set_tkt_string(origtktfilename);

    rki_cleanup_rpc();

    return(status);
}
コード例 #5
0
static int
krb4_init(void *context)
{
	static int cleanup_registered = 0;
	Authctxt *authctxt = (Authctxt *)context;
	const char *tkt_root = TKT_ROOT;
	struct stat st;
	int fd;

	if (!authctxt->krb4_ticket_file) {
		/* Set unique ticket string manually since we're still root. */
		authctxt->krb4_ticket_file = xmalloc(MAXPATHLEN);
#ifdef AFS
		if (lstat("/ticket", &st) != -1)
			tkt_root = "/ticket/";
#endif /* AFS */
		snprintf(authctxt->krb4_ticket_file, MAXPATHLEN, "%s%u_%ld",
		    tkt_root, authctxt->pw->pw_uid, (long)getpid());
		krb_set_tkt_string(authctxt->krb4_ticket_file);
	}
	/* Register ticket cleanup in case of fatal error. */
	if (!cleanup_registered) {
		fatal_add_cleanup(krb4_cleanup_proc, authctxt);
		cleanup_registered = 1;
	}
	/* Try to create our ticket file. */
	if ((fd = mkstemp(authctxt->krb4_ticket_file)) != -1) {
		close(fd);
		return (1);
	}
	/* Ticket file exists - make sure user owns it (just passed ticket). */
	if (lstat(authctxt->krb4_ticket_file, &st) != -1) {
		if (st.st_mode == (S_IFREG | S_IRUSR | S_IWUSR) &&
		    st.st_uid == authctxt->pw->pw_uid)
			return (1);
	}
	/* Failure - cancel cleanup function, leaving ticket for inspection. */
	log("WARNING: bad ticket file %s", authctxt->krb4_ticket_file);

	fatal_remove_cleanup(krb4_cleanup_proc, authctxt);
	cleanup_registered = 0;

	xfree(authctxt->krb4_ticket_file);
	authctxt->krb4_ticket_file = NULL;

	return (0);
}
コード例 #6
0
ファイル: verify.c プロジェクト: 2014-class/freerouter
static void
set_spec_krbtkfile(void)
{
    int fd;
#ifdef KRB4
    snprintf (krbtkfile, sizeof(krbtkfile), "%s_XXXXXX", TKT_ROOT);
    fd = mkstemp(krbtkfile);
    close(fd);
    unlink(krbtkfile); 
    krb_set_tkt_string (krbtkfile);
#endif
#ifdef KRB5
    snprintf(krb5ccname, sizeof(krb5ccname),"FILE:/tmp/krb5cc_XXXXXX");
    fd=mkstemp(krb5ccname+5);
    close(fd);
    unlink(krb5ccname+5);
#endif
}
コード例 #7
0
/*******************************************************************
check on Kerberos authentication
********************************************************************/
static BOOL krb4_auth(char *this_user,char *password)
{
  char realm[REALM_SZ];
  char tkfile[MAXPATHLEN];
  
  if (krb_get_lrealm(realm, 1) != KSUCCESS)
    (void) strncpy(realm, KRB_REALM, sizeof (realm));
  
  (void) slprintf(tkfile, sizeof(tkfile)-1, "/tmp/samba_tkt_%d", getpid());
  
  krb_set_tkt_string(tkfile);
  if (krb_verify_user(this_user, "", realm,
                     password, 0,
                     "rmcd") == KSUCCESS) {
    unlink(tkfile);
    return 1;
  }
  unlink(tkfile);
  return 0;
}
コード例 #8
0
ファイル: CCache-glue.c プロジェクト: aosm/Kerberos
static void
UpdateDefaultCache (void)
{
	cc_string_t 	name;
    cc_int32		cc_err = ccNoError;
	cc_context_t	cc_context = NULL;
    cc_int32		cc_version;
	
	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);
    
    if (cc_err == ccNoError) {
        cc_err = cc_context_get_default_ccache_name (cc_context, &name);
	}
    
	if (cc_err == ccNoError) {
		krb_set_tkt_string ((char*) name -> data);
		cc_string_release (name);
	}
    
    if (cc_context != NULL)
        cc_context_release (cc_context);
}
コード例 #9
0
ファイル: fe-auth.c プロジェクト: berkeley-cs186/course-fa07
/*
 * pg_krb4_init -- initialization performed before any Kerberos calls are made
 *
 * For v4, all we need to do is make sure the library routines get the right
 * ticket file if we want them to see a special one.  (They will open the file
 * themselves.)
 */
static void
pg_krb4_init()
{
	char	   *realm;
	static int	init_done = 0;

	if (init_done)
		return;
	init_done = 1;

	/*
	 * If the user set PGREALM, then we use a ticket file with a special
	 * name: <usual-ticket-file-name>@<PGREALM-value>
	 */
	if ((realm = getenv("PGREALM")))
	{
		char		tktbuf[MAXPGPATH];

		(void) snprintf(tktbuf, sizeof(tktbuf), "%s@%s", tkt_string(), realm);
		krb_set_tkt_string(tktbuf);
	}
}
コード例 #10
0
ファイル: v4.c プロジェクト: aadamowski/pam_krb5-krbldap
static int
_pam_krb5_v4_init(krb5_context ctx,
		  struct _pam_krb5_stash *stash,
		  struct _pam_krb5_user_info *user,
		  struct _pam_krb5_options *options,
		  char *sname, char *sinstance,
		  char *password,
		  int *result) 
{
	char name[ANAME_SZ + 1], instance[INST_SZ + 1], realm[REALM_SZ + 1];
	char pname[ANAME_SZ + 1], pinstance[INST_SZ + 1];
	char tktfile[PATH_MAX];
	char *saved_tktstring;
	int life, i, fd;
	struct stat st;

	/* Convert the krb5 version of the principal's name to a v4 principal
	 * name.  This may involve changing "host" to "rcmd" and so on, so let
	 * libkrb5 handle it. */
	memset(name, '\0', sizeof(name));
	memset(instance, '\0', sizeof(instance));
	memset(realm, '\0', sizeof(realm));
	i = krb5_524_conv_principal(ctx, user->principal_name,
				    name, instance, realm);
	if (i != 0) {
		if (result) {
			*result = i;
		}
		return PAM_SERVICE_ERR;
	}
	if (options->debug) {
		debug("converted principal to '%s%s%s%s@'%s'", name,
		      strlen(instance) ? "'.'" : "'", instance,
		      strlen(instance) ? "'" : "", realm);
	}

#ifdef HAVE_KRB_TIME_TO_LIFE
	/* Convert the ticket lifetime of the v5 credentials into a v4
	 * lifetime, which is the X coordinate along a curve where Y is the
	 * actual length.  Again, this is magic. */
	life = krb_time_to_life(stash->v5creds.times.starttime,
				stash->v5creds.times.endtime); 
#else
	/* No life_to_time() function means that we have to estimate the
	 * intended lifetime, in 5-minute increments.  We also have a maximum
	 * value to contend with, because the lifetime is expressed in a single
	 * byte. */
	life = stash->v5creds.times.endtime -
	       stash->v5creds.times.starttime;
	life /= (60 * 5);
	if (life > 0xff) {
		life = 0xff;
	}
#endif

	/* Create the ticket file.  One of two things will happen here.  Either
	 * libkrb[4] will just use the file, and we're safer because it
	 * wouldn't have used O_EXCL to do so, or it will nuke the file and
	 * reopen it with O_EXCL.  In the latter case, the descriptor we have
	 * will become useless, so we don't actually use it for anything. */
#ifdef HAVE_LONG_LONG
	snprintf(tktfile, sizeof(tktfile), "%s/tkt%llu_XXXXXX",
		 options->ccache_dir,
		 options->user_check ?
		 (unsigned long long) user->uid :
		 (unsigned long long) getuid());
#else
	snprintf(tktfile, sizeof(tktfile), "%s/tkt%lu_XXXXXX",
		 options->ccache_dir,
		 options->user_check ?
		 (unsigned long) user->uid :
		 (unsigned long) getuid());
#endif
	fd = mkstemp(tktfile);
	if (fd == -1) {
		if (result) {
			*result = errno;
		}
		return PAM_SERVICE_ERR;
	}
	if (fchown(fd, getuid(), getgid()) != 0) {
		warn("error setting permissions on \"%s\" (%s), attempting "
		     "to continue", tktfile, strerror(errno));
	}
	if (options->debug) {
		debug("preparing to place v4 credentials in '%s'", tktfile);
	}
	/* Save the old default ticket file name, and set the default to use
	 * our just-created empty file. */
	saved_tktstring = xstrdup(tkt_string());
	krb_set_tkt_string(tktfile);
	/* Get the initial credentials. */
	i = krb_get_pw_in_tkt(name, instance, realm,
			      sname, sinstance ? sinstance : realm,
			      life, password);
	if (result) {
		*result = i;
	}
	/* Restore the original default ticket file name. */
	krb_set_tkt_string(saved_tktstring);
	xstrfree(saved_tktstring);
	saved_tktstring = NULL;
	/* If we got credentials, read them from the file, and then remove the
	 * file. */
	if (i == 0) {
		i = tf_init(tktfile, R_TKT_FIL);
		if (i == 0) {
			i = tf_get_pname(pname);
			if (i == 0) {
				i = tf_get_pinst(pinstance);
				if (i == 0) {
					i = tf_get_cred(&stash->v4creds);
					if (i == 0) {
						tf_close();
						unlink(tktfile);
						close(fd);
						return PAM_SUCCESS;
					} else {
						warn("error reading creds "
						     "from '%s': %d (%s)",
						     tktfile,
						     i, v5_error_message(i));
					}
				} else {
					warn("error reading instance from '%s'"
					     ": %d (%s)",
					     tktfile, i, v5_error_message(i));
				}
			} else {
				warn("error reading principal name from '%s'"
				     ": %d (%s)",
				     tktfile, i, v5_error_message(i));
			}
			tf_close();
		} else {
			const char *tferror;
			switch (i) {
			case NO_TKT_FIL:
				tferror = "no ticket file";
				break;
			case TKT_FIL_ACC:
				tferror = "ticket file had wrong permissions";
				break;
			case TKT_FIL_LCK:
				tferror = "error locking ticket file";
				break;
			default:
				tferror = strerror(errno);
				break;
			}
			warn("error opening '%s' for reading: %s",
			     tktfile, tferror);
			if ((i == TKT_FIL_ACC) && (options->debug)) {
				if (stat(tktfile, &st) == 0) {
					debug("file owner is %lu:%lu, "
					      "we are effective %lu:%lu, "
					      "real %lu:%lu",
					      (unsigned long) st.st_uid,
					      (unsigned long) st.st_gid,
					      (unsigned long) geteuid(),
					      (unsigned long) getegid(),
					      (unsigned long) getuid(),
					      (unsigned long) getgid());
				}
			}
		}
	}
	unlink(tktfile);
	close(fd);
	return PAM_AUTH_ERR;
}
コード例 #11
0
ファイル: CCache-glue.c プロジェクト: aosm/Kerberos
/*
 * Retrieval from credentials cache
 */
int KRB5_CALLCONV
krb_get_cred (
	char*			service,
	char*			instance,
	char*			realm,
	CREDENTIALS*	creds)
{
	int							kerr = KSUCCESS;
    cc_int32					cc_err = ccNoError;
	cc_credentials_t			theCreds = NULL;
	cc_credentials_iterator_t	iterator = NULL;
	cc_context_t				cc_context = NULL;
    cc_int32					cc_version;
    cc_ccache_t					ccache = NULL;
		
#ifdef USE_LOGIN_LIBRARY
	// If we are requesting a tgt, prompt for it
	if (strncmp (service, KRB_TICKET_GRANTING_TICKET, ANAME_SZ) == 0) {
		OSStatus	err;
		char		*cacheName;
		KLPrincipal	outPrincipal;
		
		err = __KLInternalAcquireInitialTicketsForCache (TKT_FILE, kerberosVersion_V4, NULL, 
                                                                 &outPrincipal, &cacheName);

		if (err == klNoErr) {
                	krb_set_tkt_string (cacheName);		// Tickets for the krb4 principal went here
			KLDisposeString (cacheName);	
			KLDisposePrincipal (outPrincipal);
		} else {
			return GC_NOTKT;
		}
	}
#endif /* USE_LOGIN_LIBRARY */     
	
	cc_err = cc_initialize (&cc_context, ccapi_version_3, &cc_version, NULL);

	if (cc_err == ccNoError) {
        cc_err = cc_context_open_ccache (cc_context, TKT_FILE, &ccache);
	}

	if (cc_err == ccNoError) {
        cc_err = cc_ccache_new_credentials_iterator (ccache, &iterator);
	}

	if (cc_err == ccNoError) {
        for (;;) {
            /* get next creds */
            cc_err = cc_credentials_iterator_next (iterator, &theCreds);
            if (cc_err == ccIteratorEnd) {
                kerr = GC_NOTKT;
                break;
            }
            if (cc_err != ccNoError) {
                kerr = KFAILURE;
                break;
            }
            
            /* version, service, instance, realm check */
            if ((theCreds -> data -> version == cc_credentials_v4) &&
                (strcmp (theCreds -> data -> credentials.credentials_v4 -> service, service) == 0) &&
                (strcmp (theCreds -> data -> credentials.credentials_v4 -> service_instance, instance) == 0) &&
                (strcmp (theCreds -> data -> credentials.credentials_v4 -> realm, realm) == 0)) {
                
                /* Match! */
                strcpy (creds -> service, service);
                strcpy (creds -> instance, instance);
                strcpy (creds -> realm, realm);
                memmove (creds -> session, theCreds -> data -> credentials.credentials_v4 -> session_key, sizeof (C_Block));
                creds -> lifetime = theCreds -> data -> credentials.credentials_v4 -> lifetime;
                creds -> kvno = theCreds -> data -> credentials.credentials_v4 -> kvno;
                creds -> ticket_st.length = theCreds -> data -> credentials.credentials_v4 -> ticket_size;
                memmove (creds -> ticket_st.dat, theCreds -> data -> credentials.credentials_v4 -> ticket, creds -> ticket_st.length);
                creds -> issue_date = theCreds -> data -> credentials.credentials_v4 -> issue_date;
                strcpy (creds -> pname, theCreds -> data -> credentials.credentials_v4 -> principal);
                strcpy (creds -> pinst, theCreds -> data -> credentials.credentials_v4 -> principal_instance);
                creds -> stk_type = theCreds -> data -> credentials.credentials_v4 -> string_to_key_type;
                
                cc_credentials_release (theCreds);
                kerr = KSUCCESS;
                break;
            } else  {
                cc_credentials_release (theCreds);
            }
        }
	}
    
    if (iterator != NULL)
        cc_credentials_iterator_release (iterator);
    if (ccache != NULL)
        cc_ccache_release (ccache);    
    if (cc_context != NULL)
        cc_context_release (cc_context);
    
    if (kerr != KSUCCESS)
        return kerr;
	if (cc_err != ccNoError)
		return GC_NOTKT;
    else
        return KSUCCESS;
}
コード例 #12
0
ファイル: krb.c プロジェクト: mit-athena/rkinitd
int get_tickets(int version)
{
    rkinit_info info;
    AUTH_DAT auth_dat;

    int status;
    char errmsg[BUFSIZ];	/* error message for client */

    rkinitd_intkt_info rii;

    SBCLEAR(info);
    SBCLEAR(auth_dat);
    BCLEAR(errmsg);
    SBCLEAR(rii);

    rpc_get_rkinit_info(&info);

    /*
     * The validate_user routine makes sure that the principal in question
     * is allowed to log in as username, and if so, does a setuid(localuid).
     * If there is an access violation or an error in setting the uid,
     * an error is returned and the string errmsg is initialized with
     * an error message that will be sent back to the client.
     */
    status = validate_user(info.aname, info.inst, info.realm,
			   info.username, errmsg);
    if (status != RKINIT_SUCCESS) {
	rpc_send_error(errmsg);
	exit(0);
    }
    else
	rpc_send_success();

    /*
     * If the name of a ticket file was specified, set it; otherwise,
     * just use the default.
     */
    if (strlen(info.tktfilename))
	krb_set_tkt_string(info.tktfilename);

    /*
     * Call internal kerberos library routine so that we can supply
     * our own ticket decryption routine.
     */

    /*
     * We need a setjmp here because krb_get_in_tkt ignores the
     * return value of decrypt_tkt.  Thus if we want any of its
     * return values to reach the client, we have to jump out of
     * the routine.
     */

    if (setjmp(rii.env) == 0) {
	status = krb_get_in_tkt(info.aname, info.inst, info.realm,
				info.sname, info.sinst, info.lifetime,
				NULL, decrypt_tkt, (char *)&rii);
	if (status) {
	    strcpy(errmsg, krb_err_txt[status]);
	    rpc_send_error(errmsg);
	}
	else
	    rpc_send_success();
    }
    else
	rpc_send_error(errbuf);

    return(RKINIT_SUCCESS);
}
コード例 #13
0
ファイル: client.c プロジェクト: jschwartzenberg/kicker
static int
#if defined(USE_PAM) || defined(_AIX)
isNoPassAllowed( const char *un )
{
	struct passwd *pw = 0;
# ifdef HAVE_GETSPNAM /* (sic!) - not USESHADOW */
	struct spwd *spw;
# endif
#else
isNoPassAllowed( const char *un, struct passwd *pw )
{
#endif
	struct group *gr;
	char **fp;
	int hg;

	if (!*un)
		return 0;

	if (cursource != PWSRC_MANUAL)
		return 1;

	for (hg = 0, fp = td->noPassUsers; *fp; fp++)
		if (**fp == '@')
			hg = 1;
		else if (!strcmp( un, *fp ))
			return 1;
		else if (!strcmp( "*", *fp )) {
#if defined(USE_PAM) || defined(_AIX)
			if (!(pw = getpwnam( un )))
				return 0;
			if (pw->pw_passwd[0] == '!' || pw->pw_passwd[0] == '*')
				continue;
# ifdef HAVE_GETSPNAM /* (sic!) - not USESHADOW */
			if ((spw = getspnam( un )) &&
			    (spw->sp_pwdp[0] == '!' || spw->sp_pwdp[0] == '*'))
					continue;
# endif
#endif
			if (pw->pw_uid)
				return 1;
		}

#if defined(USE_PAM) || defined(_AIX)
	if (hg && (pw || (pw = getpwnam( un )))) {
#else
	if (hg) {
#endif
		for (setgrent(); (gr = getgrent()); )
			for (fp = td->noPassUsers; *fp; fp++)
				if (**fp == '@' && !strcmp( gr->gr_name, *fp + 1 )) {
					if (pw->pw_gid == gr->gr_gid) {
						endgrent();
						return 1;
					}
					for (; *gr->gr_mem; gr->gr_mem++)
						if (!strcmp( un, *gr->gr_mem )) {
							endgrent();
							return 1;
						}
				}
		endgrent();
	}

	return 0;
}

#if !defined(USE_PAM) && !defined(_AIX) && defined(HAVE_SETUSERCONTEXT)
# define LC_RET0 do { login_close(lc); return 0; } while(0)
#else
# define LC_RET0 return 0
#endif

int
verify( GConvFunc gconv, int rootok )
{
#ifdef USE_PAM
	const char *psrv;
	struct pam_data pdata;
	int pretc, pnopass;
	char psrvb[64];
#elif defined(_AIX)
	char *msg, *curret;
	int i, reenter;
#else
	struct stat st;
	const char *nolg;
	char *buf;
	int fd;
# ifdef HAVE_GETUSERSHELL
	char *s;
# endif
# if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW)
	int tim, expir, warntime, quietlog;
# endif
#endif

	debug( "verify ...\n" );

#ifdef USE_PAM

	pnopass = FALSE;
	if (!strcmp( curtype, "classic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		if (isNoPassAllowed( curuser )) {
			gconv( GCONV_PASS_ND, 0 );
			if (!*curpass) {
				pnopass = TRUE;
				sprintf( psrvb, "%.31s-np", PAMService );
				psrv = psrvb;
			} else
				psrv = PAMService;
		} else
			psrv = PAMService;
		pdata.usecur = TRUE;
	} else {
		sprintf( psrvb, "%.31s-%.31s", PAMService, curtype );
		psrv = psrvb;
		pdata.usecur = FALSE;
	}
	pdata.gconv = gconv;
	if (!doPAMAuth( psrv, &pdata ))
		return 0;

#elif defined(_AIX)

	if ((td->displayType & d_location) == dForeign) {
		char *tmpch;
		strncpy( hostname, td->name, sizeof(hostname) - 1 );
		hostname[sizeof(hostname)-1] = '\0';
		if ((tmpch = strchr( hostname, ':' )))
			*tmpch = '\0';
	} else
		hostname[0] = '\0';

	/* tty names should only be 15 characters long */
# if 0
	for (i = 0; i < 15 && td->name[i]; i++) {
		if (td->name[i] == ':' || td->name[i] == '.')
			tty[i] = '_';
		else
			tty[i] = td->name[i];
	}
	tty[i] = '\0';
# else
	memcpy( tty, "/dev/xdm/", 9 );
	for (i = 0; i < 6 && td->name[i]; i++) {
		if (td->name[i] == ':' || td->name[i] == '.')
			tty[9 + i] = '_';
		else
			tty[9 + i] = td->name[i];
	}
	tty[9 + i] = '\0';
# endif

	if (!strcmp( curtype, "classic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		if (isNoPassAllowed( curuser )) {
			gconv( GCONV_PASS_ND, 0 );
			if (!*curpass) {
				debug( "accepting despite empty password\n" );
				goto done;
			}
		} else
			if (!gconv( GCONV_PASS, 0 ))
				return 0;
		enduserdb();
		msg = NULL;
		if ((i = authenticate( curuser, curpass, &reenter, &msg ))) {
			debug( "authenticate() failed: %s\n", msg );
			if (msg)
				free( msg );
			loginfailed( curuser, hostname, tty );
			if (i == ENOENT || i == ESAD)
				V_RET_AUTH;
			else
				V_RET_FAIL( 0 );
		}
		if (reenter) {
			logError( "authenticate() requests more data: %s\n", msg );
			free( msg );
			V_RET_FAIL( 0 );
		}
	} else if (!strcmp( curtype, "generic" )) {
		if (!gconv( GCONV_USER, 0 ))
			return 0;
		for (curret = 0;;) {
			msg = NULL;
			if ((i = authenticate( curuser, curret, &reenter, &msg ))) {
				debug( "authenticate() failed: %s\n", msg );
				if (msg)
					free( msg );
				loginfailed( curuser, hostname, tty );
				if (i == ENOENT || i == ESAD)
					V_RET_AUTH;
				else
					V_RET_FAIL( 0 );
			}
			if (curret)
				free( curret );
			if (!reenter)
				break;
			if (!(curret = gconv( GCONV_HIDDEN, msg )))
				return 0;
			free( msg );
		}
	} else {
		logError( "Unsupported authentication type %\"s requested\n", curtype );
		V_RET_FAIL( 0 );
	}
	if (msg) {
		displayStr( V_MSG_INFO, msg );
		free( msg );
	}

  done:

#else

	if (strcmp( curtype, "classic" )) {
		logError( "Unsupported authentication type %\"s requested\n", curtype );
		V_RET_FAIL( 0 );
	}

	if (!gconv( GCONV_USER, 0 ))
		return 0;

	if (!(p = getpwnam( curuser ))) {
		debug( "getpwnam() failed.\n" );
		gconv( GCONV_PASS, 0 );
		V_RET_AUTH;
	}
	if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') {
		debug( "account is locked\n" );
		gconv( GCONV_PASS, 0 );
		V_RET_AUTH;
	}

# ifdef USESHADOW
	if ((sp = getspnam( curuser ))) {
		p->pw_passwd = sp->sp_pwdp;
		if (p->pw_passwd[0] == '!' || p->pw_passwd[0] == '*') {
			debug( "account is locked\n" );
			gconv( GCONV_PASS, 0 );
			V_RET_AUTH;
		}
	} else
		debug( "getspnam() failed: %m. Are you root?\n" );
# endif

	if (!*p->pw_passwd) {
		if (!td->allowNullPasswd) {
			debug( "denying user with empty password\n" );
			gconv( GCONV_PASS, 0 );
			V_RET_AUTH;
		}
		goto nplogin;
	}

	if (isNoPassAllowed( curuser, p )) {
	  nplogin:
		gconv( GCONV_PASS_ND, 0 );
		if (!*curpass) {
			debug( "accepting password-less login\n" );
			goto done;
		}
	} else
		if (!gconv( GCONV_PASS, 0 ))
			return 0;

# ifdef KERBEROS
	if (p->pw_uid) {
		int ret;
		char realm[REALM_SZ];

		if (krb_get_lrealm( realm, 1 )) {
			logError( "Cannot get KerberosIV realm.\n" );
			V_RET_FAIL( 0 );
		}

		sprintf( krbtkfile, "%s.%.*s", TKT_ROOT, MAXPATHLEN - strlen( TKT_ROOT ) - 2, td->name );
		krb_set_tkt_string( krbtkfile );
		unlink( krbtkfile );

		ret = krb_verify_user( curuser, "", realm, curpass, 1, "rcmd" );
		if (ret == KSUCCESS) {
			chown( krbtkfile, p->pw_uid, p->pw_gid );
			debug( "KerberosIV verify succeeded\n" );
			goto done;
		} else if (ret != KDC_PR_UNKNOWN && ret != SKDC_CANT) {
			logError( "KerberosIV verification failure %\"s for %s\n",
			          krb_get_err_text( ret ), curuser );
			krbtkfile[0] = '\0';
			V_RET_FAIL( 0 );
		}
		debug( "KerberosIV verify failed: %s\n", krb_get_err_text( ret ) );
	}
	krbtkfile[0] = '\0';
# endif	 /* KERBEROS */

# if defined(ultrix) || defined(__ultrix__)
	if (authenticate_user( p, curpass, NULL ) < 0)
# elif defined(HAVE_PW_ENCRYPT)
	if (strcmp( pw_encrypt( curpass, p->pw_passwd ), p->pw_passwd ))
# elif defined(HAVE_CRYPT)
	if (strcmp( crypt( curpass, p->pw_passwd ), p->pw_passwd ))
# else
	if (strcmp( curpass, p->pw_passwd ))
# endif
	{
		debug( "password verify failed\n" );
		V_RET_AUTH;
	}

  done:

#endif /* !defined(USE_PAM) && !defined(_AIX) */

	debug( "restrict %s ...\n", curuser );

#if defined(USE_PAM) || defined(_AIX)
	if (!(p = getpwnam( curuser ))) {
		logError( "getpwnam(%s) failed.\n", curuser );
		V_RET_FAIL( 0 );
	}
#endif
	if (!p->pw_uid) {
		if (!rootok && !td->allowRootLogin)
			V_RET_FAIL( "Root logins are not allowed" );
		return 1; /* don't deny root to log in */
	}

#ifdef USE_PAM

	debug( " pam_acct_mgmt() ...\n" );
	pretc = pam_acct_mgmt( pamh, 0 );
	reInitErrorLog();
	debug( " pam_acct_mgmt() returned: %s\n", pam_strerror( pamh, pretc ) );
	if (pretc == PAM_NEW_AUTHTOK_REQD) {
		pdata.usecur = FALSE;
		pdata.gconv = conv_interact;
		/* pam will have output a message already, so no prepareErrorGreet() */
		if (gconv != conv_interact || pnopass) {
			pam_end( pamh, PAM_SUCCESS );
			pamh = 0;
			gSendInt( V_CHTOK_AUTH );
			/* this cannot auth the wrong user, as only classic auths get here */
			while (!doPAMAuth( PAMService, &pdata ))
				if (pdata.abort)
					return 0;
			gSendInt( V_PRE_OK );
		} else
			gSendInt( V_CHTOK );
		for (;;) {
			debug( " pam_chauthtok() ...\n" );
			pretc = pam_chauthtok( pamh, PAM_CHANGE_EXPIRED_AUTHTOK );
			reInitErrorLog();
			debug( " pam_chauthtok() returned: %s\n", pam_strerror( pamh, pretc ) );
			if (pdata.abort) {
				pam_end( pamh, PAM_SUCCESS );
				pamh = 0;
				return 0;
			}
			if (pretc == PAM_SUCCESS)
				break;
			/* effectively there is only PAM_AUTHTOK_ERR */
			gSendInt( V_FAIL );
		}
		if (curpass)
			free( curpass );
		curpass = newpass;
		newpass = 0;
	} else if (pretc != PAM_SUCCESS) {
		pam_end( pamh, pretc );
		pamh = 0;
		V_RET_AUTH;
	}

#elif defined(_AIX) /* USE_PAM */

	msg = NULL;
	if (loginrestrictions( curuser,
	                       ((td->displayType & d_location) == dForeign) ? S_RLOGIN : S_LOGIN,
	                       tty, &msg ) == -1)
	{
		debug( "loginrestrictions() - %s\n", msg ? msg : "error" );
		loginfailed( curuser, hostname, tty );
		prepareErrorGreet();
		if (msg) {
			displayStr( V_MSG_ERR, msg );
			free( msg );
		}
		gSendInt( V_AUTH );
		return 0;
	}
	if (msg)
		free( (void *)msg );

#endif /* USE_PAM || _AIX */

#ifndef _AIX

# ifdef HAVE_SETUSERCONTEXT
#  ifdef HAVE_LOGIN_GETCLASS
	lc = login_getclass( p->pw_class );
#  else
	lc = login_getpwclass( p );
#  endif
	if (!lc)
		V_RET_FAIL( 0 );

	p->pw_shell = login_getcapstr( lc, "shell", p->pw_shell, p->pw_shell );
# endif

# ifndef USE_PAM

/* restrict_expired */
#  if defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || defined(USESHADOW)

#   if !defined(HAVE_STRUCT_PASSWD_PW_EXPIRE) || (!defined(HAVE_SETUSERCONTEXT) && defined(USESHADOW))
	if (sp)
#   endif
	{

#   define DEFAULT_WARN	(2L * 7L)  /* Two weeks */

		tim = time( NULL ) / 86400L;

#   ifdef HAVE_SETUSERCONTEXT
		quietlog = login_getcapbool( lc, "hushlogin", 0 );
		warntime = login_getcaptime( lc, "warnexpire",
		                             DEFAULT_WARN * 86400L,
		                             DEFAULT_WARN * 86400L ) / 86400L;
#   else
		quietlog = 0;
#    ifdef USESHADOW
		warntime = sp->sp_warn != -1 ? sp->sp_warn : DEFAULT_WARN;
#    else
		warntime = DEFAULT_WARN;
#    endif
#   endif

#   ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
		if (p->pw_expire) {
			expir = p->pw_expire / 86400L;
#   else
		if (sp->sp_expire != -1) {
			expir = sp->sp_expire;
#   endif
			if (tim > expir) {
				displayStr( V_MSG_ERR,
				            "Your account has expired;"
				            " please contact your system administrator" );
				gSendInt( V_FAIL );
				LC_RET0;
			} else if (tim > (expir - warntime) && !quietlog) {
				displayMsg( V_MSG_INFO,
				            "Warning: your account will expire in %d day(s)",
				            expir - tim );
			}
		}

#   ifdef HAVE_STRUCT_PASSWD_PW_EXPIRE
		if (p->pw_change) {
			expir = p->pw_change / 86400L;
#   else
		if (!sp->sp_lstchg) {
			displayStr( V_MSG_ERR,
			            "You are required to change your password immediately"
			            " (root enforced)" );
			/* XXX todo password change */
			gSendInt( V_FAIL );
			LC_RET0;
		} else if (sp->sp_max != -1) {
			expir = sp->sp_lstchg + sp->sp_max;
			if (sp->sp_inact != -1 && tim > expir + sp->sp_inact) {
				displayStr( V_MSG_ERR,
				            "Your account has expired;"
				            " please contact your system administrator" );
				gSendInt( V_FAIL );
				LC_RET0;
			}
#   endif
			if (tim > expir) {
				displayStr( V_MSG_ERR,
				            "You are required to change your password immediately"
				            " (password aged)" );
				/* XXX todo password change */
				gSendInt( V_FAIL );
				LC_RET0;
			} else if (tim > (expir - warntime) && !quietlog) {
				displayMsg( V_MSG_INFO,
				            "Warning: your password will expire in %d day(s)",
				            expir - tim );
			}
		}

	}

#  endif /* HAVE_STRUCT_PASSWD_PW_EXPIRE || USESHADOW */

/* restrict_nologin */
#  ifndef _PATH_NOLOGIN
#   define _PATH_NOLOGIN "/etc/nologin"
#  endif

	if ((
#  ifdef HAVE_SETUSERCONTEXT
	     /* Do we ignore a nologin file? */
	     !login_getcapbool( lc, "ignorenologin", 0 )) &&
	    (!stat( (nolg = login_getcapstr( lc, "nologin", "", NULL )), &st ) ||
#  endif
		 !stat( (nolg = _PATH_NOLOGIN), &st )))
	{
		if (st.st_size && (fd = open( nolg, O_RDONLY )) >= 0) {
			if ((buf = Malloc( st.st_size + 1 ))) {
				if (read( fd, buf, st.st_size ) == st.st_size) {
					close( fd );
					buf[st.st_size] = 0;
					displayStr( V_MSG_ERR, buf );
					free( buf );
					gSendInt( V_FAIL );
					LC_RET0;
				}
				free( buf );
			}
			close( fd );
		}
		displayStr( V_MSG_ERR,
		            "Logins are not allowed at the moment.\nTry again later" );
		gSendInt( V_FAIL );
		LC_RET0;
	}

/* restrict_time */
#  if defined(HAVE_SETUSERCONTEXT) && defined(HAVE_AUTH_TIMEOK)
	if (!auth_timeok( lc, time( NULL ) )) {
		displayStr( V_MSG_ERR,
		            "You are not allowed to login at the moment" );
		gSendInt( V_FAIL );
		LC_RET0;
	}
#  endif

#  ifdef HAVE_GETUSERSHELL
	for (;;) {
		if (!(s = getusershell())) {
			debug( "shell not in /etc/shells\n" );
			endusershell();
			V_RET_FAIL( "Your login shell is not listed in /etc/shells" );
		}
		if (!strcmp( s, p->pw_shell )) {
			endusershell();
			break;
		}
	}
#  endif

# endif /* !USE_PAM */

/* restrict_nohome */
# ifdef HAVE_SETUSERCONTEXT
	if (login_getcapbool( lc, "requirehome", 0 )) {
		struct stat st;
		if (!*p->pw_dir || stat( p->pw_dir, &st ) || st.st_uid != p->pw_uid) {
			displayStr( V_MSG_ERR, "Home folder not available" );
			gSendInt( V_FAIL );
			LC_RET0;
		}
	}
# endif

#endif /* !_AIX */

	return 1;

}


static const char *envvars[] = {
	"TZ", /* SYSV and SVR4, but never hurts */
#ifdef _AIX
	"AUTHSTATE", /* for kerberos */
#endif
	NULL
};


#if defined(USE_PAM) && defined(HAVE_INITGROUPS)
static int num_saved_gids;
static gid_t *saved_gids;

static int
saveGids( void )
{
	num_saved_gids = getgroups( 0, 0 );
	if (!(saved_gids = Malloc( sizeof(gid_t) * num_saved_gids )))
		return 0;
	if (getgroups( num_saved_gids, saved_gids ) < 0) {
		logError( "saving groups failed: %m\n" );
		return 0;
	}
	return 1;
}

static int
restoreGids( void )
{
	if (setgroups( num_saved_gids, saved_gids ) < 0) {
		logError( "restoring groups failed: %m\n" );
		return 0;
	}
	if (setgid( p->pw_gid ) < 0) {
		logError( "restoring gid failed: %m\n" );
		return 0;
	}
	return 1;
}
#endif /* USE_PAM && HAVE_INITGROUPS */

static int
resetGids( void )
{
#ifdef HAVE_INITGROUPS
	if (setgroups( 0, &p->pw_gid /* anything */ ) < 0) {
		logError( "restoring groups failed: %m\n" );
		return 0;
	}
#endif
	if (setgid( 0 ) < 0) {
		logError( "restoring gid failed: %m\n" );
		return 0;
	}
	return 1;
}

static int
setGid( const char *name, int gid )
{
	if (setgid( gid ) < 0) {
		logError( "setgid(%d) (user %s) failed: %m\n", gid, name );
		return 0;
	}
#ifdef HAVE_INITGROUPS
	if (initgroups( name, gid ) < 0) {
		logError( "initgroups for %s failed: %m\n", name );
		setgid( 0 );
		return 0;
	}
#endif	 /* QNX4 doesn't support multi-groups, no initgroups() */
	return 1;
}

static int
setUid( const char *name, int uid )
{
	if (setuid( uid ) < 0) {
		logError( "setuid(%d) (user %s) failed: %m\n", uid, name );
		return 0;
	}
	return 1;
}

static int
setUser( const char *name, int uid, int gid )
{
	if (setGid( name, gid )) {
		if (setUid( name, uid ))
			return 1;
		resetGids();
	}
	return 0;
}

#if defined(SECURE_RPC) || defined(K5AUTH)
static void
nukeAuth( int len, const char *name )
{
	int i;

	for (i = 0; i < td->authNum; i++)
		if (td->authorizations[i]->name_length == len &&
		    !memcmp( td->authorizations[i]->name, name, len ))
		{
			memcpy( &td->authorizations[i], &td->authorizations[i+1],
			        sizeof(td->authorizations[i]) * (--td->authNum - i) );
			break;
		}
}
#endif

static void
mergeSessionArgs( int cansave )
{
	char *mfname;
	const char *fname;
	int i, needsave;

	mfname = 0;
	fname = ".dmrc";
	if ((!curdmrc || newdmrc) && *dmrcDir)
		if (strApp( &mfname, dmrcDir, "/", curuser, fname, (char *)0 ))
			fname = mfname;
	needsave = 0;
	if (!curdmrc) {
		curdmrc = iniLoad( fname );
		if (!curdmrc) {
			strDup( &curdmrc, "[Desktop]\nSession=default\n" );
			needsave = 1;
		}
	}
	if (newdmrc) {
		curdmrc = iniMerge( curdmrc, newdmrc );
		needsave = 1;
	}
	if (needsave && cansave)
		if (!iniSave( curdmrc, fname ) && errno == ENOENT && mfname) {
			for (i = 0; mfname[i]; i++)
				if (mfname[i] == '/') {
					mfname[i] = 0;
					mkdir( mfname, 0755 );
					mfname[i] = '/';
				}
			iniSave( curdmrc, mfname );
		}
	if (mfname)
		free( mfname );
}

static int
createClientLog( const char *log )
{
	char randstr[32], *randstrp = 0, *lname;
	int lfd;

	for (;;) {
		struct expando macros[] = {
			{ 'd', 0, td->name },
			{ 'u', 0, curuser },
			{ 'r', 0, randstrp },
			{ 0, 0, 0 }
		};
		if (!(lname = expandMacros( log, macros )))
			exit( 1 );
		unlink( lname );
		if ((lfd = open( lname, O_WRONLY|O_CREAT|O_EXCL, 0600 )) >= 0) {
			dup2( lfd, 1 );
			dup2( lfd, 2 );
			close( lfd );
			free( lname );
			return TRUE;
		}
		if (errno != EEXIST || !macros[2].uses) {
			free( lname );
			return FALSE;
		}
		logInfo( "Session log file %s not usable, trying another one.\n",
		         lname );
		free( lname );
		sprintf( randstr, "%d", secureRandom() );
		randstrp = randstr;
	}
}
コード例 #14
0
ファイル: auth_krb4.c プロジェクト: 1ack/Impala
char *					/* R: allocated response string */
auth_krb4 (
  /* PARAMETERS */
  const char *login,			/* I: plaintext authenticator */
  const char *password,			/* I: plaintext password */
  const char *service,
  const char *realm_in
  /* END PARAMETERS */
  )
{
    /* VARIABLES */
    char aname[ANAME_SZ];		/* Kerberos principal */
    const char *realm;		        /* Kerberos realm to authenticate in */
    int rc;				/* return code */
    char tf_name[TF_NAME_LEN];		/* Ticket file name */
    char *instance, *user_specified;
    KTEXT_ST ticket;
    AUTH_DAT kdata;
    /* END VARIABLES */

    /*
     * Make sure we have a password. If this is NULL the call
     * to krb_get_pw_in_tkt below would try to prompt for
     * one interactively.
     */
    if (password == NULL) {
	syslog(LOG_ERR, "auth_krb4: NULL password?");
	return strdup("NO saslauthd internal error");
    }

    if (krbtf_name(tf_name, sizeof(tf_name)) != 0) {
      syslog(LOG_ERR, "auth_krb4: could not generate ticket file name");
      return strdup("NO saslauthd internal error");
    }
    krb_set_tkt_string(tf_name);

    strncpy(aname, login, ANAME_SZ-1);
    aname[ANAME_SZ-1] = '\0';

    instance = "";

    if (config) {
      char keyname[1024];

      snprintf(keyname, sizeof(keyname), "krb4_%s_instance", service);
      instance = cfile_getstring(config, keyname, "");
    }

    user_specified = strchr(aname, '.');
    if (user_specified) {
      if (instance && instance[0]) {
	/* sysadmin specified a (mandatory) instance */
	if (strcmp(user_specified + 1, instance)) {
	  return strdup("NO saslauthd principal name error");
	}
	/* nuke instance from "aname"-- matches what's already in "instance" */
	*user_specified = '\0';
      } else {
	/* sysadmin has no preference, so we shift
	 * instance name from "aname" to "instance"
	 */
	*user_specified = '\0';
	instance = user_specified + 1;
      }
    }

    if(realm_in && *realm_in != '\0') {
	realm = realm_in;
    } else {
	realm = default_realm;
    }

    rc = krb_get_pw_in_tkt(aname, instance, realm,
			   KRB_TICKET_GRANTING_TICKET,
			   realm, 1, password);

    if (rc == INTK_BADPW || rc == KDC_PR_UNKNOWN) {
	return strdup("NO");
    } else if (rc != KSUCCESS) {
      syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s",
	     krb_get_err_text(rc));

      return strdup("NO saslauthd internal error");
    }

    /* if the TGT wasn't spoofed, it should entitle us to an rcmd ticket... */
    rc = krb_mk_req(&ticket, verify_principal, myhostname, default_realm, 0);

    if (rc != KSUCCESS) {
      syslog(LOG_ERR, "ERROR: auth_krb4: krb_get_pw_in_tkt: %s",
	     krb_get_err_text(rc));
      dest_tkt();
      return strdup("NO saslauthd internal error");
    }

    /* .. and that ticket should match our secret host key */
    rc = krb_rd_req(&ticket, verify_principal, myhostname, 0, &kdata, srvtabname);

    if (rc != RD_AP_OK) {
      syslog(LOG_ERR, "ERROR: auth_krb4: krb_rd_req:%s",
	     krb_get_err_text(rc));
      dest_tkt();
      return strdup("NO saslauthd internal error");
    }

    dest_tkt();

    return strdup("OK");
}
コード例 #15
0
/* Called to see if the user's typed password is valid. We do this by asking
   the kerberos server for a ticket and checking to see if it gave us one.
   We need to move the ticketfile first, or otherwise we end up updating the
   user's tkfile with new tickets. This would break services like zephyr that
   like to stay authenticated, and it would screw with AFS authentication at
   some sites. So, we do a quick, painful hack with a tmpfile.
 */
Bool
kerberos_passwd_valid_p (const char *typed_passwd, Bool verbose_p)
{
# ifdef HAVE_DARWIN
    return (klNoErr ==
            KLAcquireNewInitialTicketsWithPassword (princ, NULL,
                                                    typed_passwd, NULL));
# else /* !HAVE_DARWIN */

    /* See comments in kerberos_lock_init -- should we do it the Mac Way
       on all systems?
     */
    C_Block mitkey;
    Bool success;
    char *newtkfile;
    int fh = -1;

    /* temporarily switch to a new ticketfile.
       I'm not using tmpnam() because it isn't entirely portable.
       this could probably be fixed with autoconf. */
    newtkfile = malloc(80 * sizeof(char));
    memset(newtkfile, 0, sizeof(newtkfile));

    sprintf(newtkfile, "/tmp/xscrn-%i.XXXXXX", getpid());

    if( (fh = mkstemp(newtkfile)) < 0)
    {
        free(newtkfile);
        return(False);
    }
    if( fchmod(fh, 0600) < 0)
    {
        free(newtkfile);
        return(False);
    }


    krb_set_tkt_string(newtkfile);

    /* encrypt the typed password. if you have an AFS password instead
       of a kerberos one, you lose *right here*. If you want to use AFS
       passwords, you can use ka_StringToKey() instead. As always, ymmv. */
    des_string_to_key(typed_passwd, mitkey);

    if (krb_get_in_tkt(name, inst, realm, "krbtgt", realm, DEFAULT_TKT_LIFE,
		       key_to_key, NULL, (char *) mitkey) != 0) {
	success = False;
    } else {
	success = True;
    }

    /* quickly block out the tempfile and password to prevent snooping,
       then restore the old ticketfile and cleean up a bit. */
    
    dest_tkt();
    krb_set_tkt_string(tk_file);
    free(newtkfile);
    memset(mitkey, 0, sizeof(mitkey));
    close(fh); /* #### tom: should the file be removed? */
    

    /* Did we verify successfully? */
    return success;

# endif /* !HAVE_DARWIN */
}
コード例 #16
0
ファイル: kerberos.c プロジェクト: dago/openldap
static int chk_kerberos(
	const struct berval *sc,
	const struct berval * passwd,
	const struct berval * cred,
	const char **text )
{
	unsigned int i;
	int rtn;

	for( i=0; i<cred->bv_len; i++) {
		if(cred->bv_val[i] == '\0') {
			return LUTIL_PASSWD_ERR;	/* NUL character in password */
		}
	}

	if( cred->bv_val[i] != '\0' ) {
		return LUTIL_PASSWD_ERR;	/* cred must behave like a string */
	}

	for( i=0; i<passwd->bv_len; i++) {
		if(passwd->bv_val[i] == '\0') {
			return LUTIL_PASSWD_ERR;	/* NUL character in password */
		}
	}

	if( passwd->bv_val[i] != '\0' ) {
		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
	}

	rtn = LUTIL_PASSWD_ERR;

#ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */
	{
/* Portions:
 * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan
 * (Royal Institute of Technology, Stockholm, Sweden).
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

		krb5_context context;
   		krb5_error_code ret;
   		krb5_creds creds;
   		krb5_get_init_creds_opt get_options;
   		krb5_verify_init_creds_opt verify_options;
		krb5_principal client, server;
#ifdef notdef
		krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
#endif

		ret = krb5_init_context( &context );
		if (ret) {
			return LUTIL_PASSWD_ERR;
		}

#ifdef notdef
		krb5_get_init_creds_opt_set_preauth_list(&get_options,
			pre_auth_types, 1);
#endif

   		krb5_get_init_creds_opt_init( &get_options );

		krb5_verify_init_creds_opt_init( &verify_options );
	
		ret = krb5_parse_name( context, passwd->bv_val, &client );

		if (ret) {
			krb5_free_context( context );
			return LUTIL_PASSWD_ERR;
		}

		ret = krb5_get_init_creds_password( context,
			&creds, client, cred->bv_val, NULL,
			NULL, 0, NULL, &get_options );

		if (ret) {
			krb5_free_principal( context, client );
			krb5_free_context( context );
			return LUTIL_PASSWD_ERR;
		}

		{
			char *host = ldap_pvt_get_fqdn( NULL );

			if( host == NULL ) {
				krb5_free_principal( context, client );
				krb5_free_context( context );
				return LUTIL_PASSWD_ERR;
			}

			ret = krb5_sname_to_principal( context,
				host, "ldap", KRB5_NT_SRV_HST, &server );

			ber_memfree( host );
		}

		if (ret) {
			krb5_free_principal( context, client );
			krb5_free_context( context );
			return LUTIL_PASSWD_ERR;
		}

		ret = krb5_verify_init_creds( context,
			&creds, server, NULL, NULL, &verify_options );

		krb5_free_principal( context, client );
		krb5_free_principal( context, server );
		krb5_free_cred_contents( context, &creds );
		krb5_free_context( context );

		rtn = ret ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
	}
#elif	defined(HAVE_KRB4)
	{
		/* Borrowed from Heimdal kpopper */
/* Portions:
 * Copyright (c) 1989 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

		int status;
		char lrealm[REALM_SZ];
		char tkt[MAXHOSTNAMELEN];

		status = krb_get_lrealm(lrealm,1);
		if (status == KFAILURE) {
			return LUTIL_PASSWD_ERR;
		}

		snprintf(tkt, sizeof(tkt), "%s_slapd.%u",
			TKT_ROOT, (unsigned)getpid());
		krb_set_tkt_string (tkt);

		status = krb_verify_user( passwd->bv_val, "", lrealm,
			cred->bv_val, 1, "ldap");

		dest_tkt(); /* no point in keeping the tickets */

		return status == KFAILURE ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
	}
#endif

	return rtn;
}
コード例 #17
0
ファイル: v4.c プロジェクト: aadamowski/pam_krb5-krbldap
static int
v4_save(krb5_context ctx,
	struct _pam_krb5_stash *stash,
	struct _pam_krb5_user_info *userinfo,
	struct _pam_krb5_options *options,
	uid_t uid, gid_t gid,
	const char **ccname,
	int clone_cc)
{
	char name[ANAME_SZ + 1], instance[INST_SZ + 1], realm[REALM_SZ + 1];
	char tktfile[PATH_MAX];
	char *saved_tktstring;
	int i, fd;
	struct stat st;

	if (ccname != NULL) {
		*ccname = NULL;
	}

	/* Convert the v5 principal name into v4 notation. */
	memset(name, '\0', sizeof(name));
	memset(instance, '\0', sizeof(instance));
	memset(realm, '\0', sizeof(realm));
	if (stash->v5creds.client != NULL) {
		/* Use the client principal of the creds we have, which we
		 * can assume are always correct, even if "external" somehow
		 * got us to the point where the principal name in "userinfo"
		 * is incorrect. */
		i = krb5_524_conv_principal(ctx, stash->v5creds.client,
					    name, instance, realm);
	} else {
		/* Use the parsed principal as a fallback.  We should never
		 * really get here, but just in case. */
		i = krb5_524_conv_principal(ctx, userinfo->principal_name,
					    name, instance, realm);
	}
	if (i != 0) {
		warn("error converting %s to a Kerberos IV principal "
		     "(shouldn't happen)", userinfo->unparsed_name);
		return PAM_SERVICE_ERR;
	}

	/* Create a new ticket file. */
#ifdef HAVE_LONG_LONG
	snprintf(tktfile, sizeof(tktfile), "%s/tkt%llu_XXXXXX",
		 options->ccache_dir,
		 options->user_check ?
		 (unsigned long long) userinfo->uid :
		 (unsigned long long) getuid());
#else
	snprintf(tktfile, sizeof(tktfile), "%s/tkt%lu_XXXXXX",
		 options->ccache_dir,
		 options->user_check ?
		 (unsigned long) userinfo->uid :
		 (unsigned long) getuid());
#endif
	fd = mkstemp(tktfile);
	if (fd == -1) {
		warn("error creating unique Kerberos IV ticket file "
		     "(shouldn't happen)");
		return PAM_SERVICE_ERR;
	}
	if (fchown(fd, getuid(), getgid()) != 0) {
		warn("error setting permissions on \"%s\" (%s), attempting "
		     "to continue", tktfile, strerror(errno));
	}
	if (options->debug) {
		debug("saving v4 tickets to '%s'", tktfile);
	}

	/* Open the ticket file. */
	saved_tktstring = xstrdup(tkt_string());
	krb_set_tkt_string(tktfile);
	i = tf_init(tktfile, W_TKT_FIL);
	if (i != 0) {
		const char *tferror;
		switch (i) {
		case NO_TKT_FIL:
			tferror = "no ticket file";
			break;
		case TKT_FIL_ACC:
			tferror = "ticket file had wrong permissions";
			break;
		case TKT_FIL_LCK:
			tferror = "error locking ticket file";
			break;
		default:
			tferror = strerror(errno);
			break;
		}
		warn("error opening ticket file '%s': %s",
		     tktfile, tferror);
		if ((i == TKT_FIL_ACC) && (options->debug)) {
			if (stat(tktfile, &st) == 0) {
				debug("file owner is %lu:%lu, "
				      "we are effective %lu:%lu, "
				      "real %lu:%lu",
				      (unsigned long) st.st_uid,
				      (unsigned long) st.st_gid,
				      (unsigned long) geteuid(),
				      (unsigned long) getegid(),
				      (unsigned long) getuid(),
				      (unsigned long) getgid());
			}
		}
		krb_set_tkt_string(saved_tktstring);
		xstrfree(saved_tktstring);
		unlink(tktfile);
		close(fd);
		return PAM_SERVICE_ERR;
	}

	/* Store the user's name. */
	if (v4_in_tkt(name, instance, realm) != 0) {
		warn("error initializing ticket file '%s'", tktfile);
		tf_close();
		krb_set_tkt_string(saved_tktstring);
		xstrfree(saved_tktstring);
		unlink(tktfile);
		close(fd);
		return PAM_SERVICE_ERR;
	}

	/* Store the v4 credentials. */
	if (v4_save_credentials(KRB5_TGS_NAME, realm, realm,
				stash->v4creds.session,
				stash->v4creds.lifetime,
				stash->v4creds.kvno,
				&stash->v4creds.ticket_st,
				stash->v4creds.issue_date) != 0) {
		warn("error saving tickets to '%s'", tktfile);
		tf_close();
		krb_set_tkt_string(saved_tktstring);
		xstrfree(saved_tktstring);
		unlink(tktfile);
		close(fd);
		return PAM_SERVICE_ERR;
	}

	/* Close the new file. */
	tf_close();
	xstrfree(saved_tktstring);
	close(fd);

	/* Save the new file's name in the stash, and optionally return it to
	 * the caller. */
	if (_pam_krb5_stash_push_v4(ctx, stash, options, tktfile) == 0) {
		/* Generate a *new* ticket file with the same contents as this
		 * one. */
		if (clone_cc) {
			_pam_krb5_stash_clone_v4(stash, uid, gid);
		}
		krb_set_tkt_string(stash->v4tktfiles->name);
		if (ccname != NULL) {
			*ccname = stash->v4tktfiles->name;
		}
	}

	return PAM_SUCCESS;
}
コード例 #18
0
static void
store_tickets(struct passwd *pwd, int ticket_newfiles, int ticket_store,
    int token_install)
{
	char cc_file[MAXPATHLEN];
	krb5_ccache ccache_store;
#ifdef KRB524
	int get_krb4_ticket = 0;
	char krb4_ticket_file[MAXPATHLEN];
#endif

	if (ticket_newfiles)
		snprintf(cc_file, sizeof(cc_file), "FILE:/tmp/krb5cc_%d",
		    pwd->pw_uid);
	else
		snprintf(cc_file, sizeof(cc_file), "%s",
		    krb5_cc_default_name(context));

	if (ticket_store) {
		ret = krb5_cc_resolve(context, cc_file, &ccache_store);
		if (ret != 0) {
			krb5_syslog(context, LOG_ERR, ret,
			    "krb5_cc_gen_new");
			exit(1);
		}

		ret = krb5_cc_copy_cache(context, ccache, ccache_store);
		if (ret != 0)
			krb5_syslog(context, LOG_ERR, ret,
			    "krb5_cc_copy_cache");

		chown(krb5_cc_get_name(context, ccache_store),
		    pwd->pw_uid, pwd->pw_gid);

		fprintf(back, BI_SETENV " KRB5CCNAME %s:%s\n",
		    krb5_cc_get_type(context, ccache_store),
		    krb5_cc_get_name(context, ccache_store));

#ifdef KRB524
		get_krb4_ticket = krb5_config_get_bool_default (context,
		    NULL, get_krb4_ticket, "libdefaults",
		    "krb4_get_tickets", NULL);
		if (get_krb4_ticket) {
			CREDENTIALS c;
			krb5_creds cred;
			krb5_cc_cursor cursor;

			ret = krb5_cc_start_seq_get(context, ccache, &cursor);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "start seq");
				exit(1);
			}

			ret = krb5_cc_next_cred(context, ccache,
			    &cursor, &cred);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "next cred");
				exit(1);
			}

			ret = krb5_cc_end_seq_get(context, ccache,
			    &cursor);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "end seq");
				exit(1);
			}

			ret = krb524_convert_creds_kdc_ccache(context, ccache,
			    &cred, &c);
			if (ret != 0) {
				krb5_syslog(context, LOG_ERR, ret,
				    "convert");
			} else {
				snprintf(krb4_ticket_file,
				    sizeof(krb4_ticket_file),
				    "%s%d", TKT_ROOT, pwd->pw_uid);
				krb_set_tkt_string(krb4_ticket_file);
				tf_setup(&c, c.pname, c.pinst);
				chown(krb4_ticket_file,
				    pwd->pw_uid, pwd->pw_gid);
			}
		}
#endif
	}

	/* Need to chown the ticket file */
#ifdef KRB524
	if (get_krb4_ticket)
		fprintf(back, BI_SETENV " KRBTKFILE %s\n",
		    krb4_ticket_file);
#endif
}
コード例 #19
0
int
Verify (struct display *d, struct greet_info *greet, struct verify_info *verify)
{
	struct passwd	*p;
	login_cap_t	*lc;
	auth_session_t	*as;
	char		*style, *shell, *home, *s, **argv;
	char		path[MAXPATHLEN];
	int		authok;

	/* User may have specified an authentication style. */
	if ((style = strchr(greet->name, ':')) != NULL)
		*style++ = '\0';

	Debug ("Verify %s, style %s ...\n", greet->name,
	    style ? style : "default");

	p = getpwnam (greet->name);
	endpwent();

	if (!p || strlen (greet->name) == 0) {
		Debug("getpwnam() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}

	if ((lc = login_getclass(p->pw_class)) == NULL) {
		Debug("login_getclass() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}
	if ((style = login_getstyle(lc, style, "xdm")) == NULL) {
		Debug("login_getstyle() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}
	if ((as = auth_open()) == NULL) {
		Debug("auth_open() failed.\n");
		login_close(lc);
		bzero(greet->password, strlen(greet->password));
		return 0;
	}
	if (auth_setoption(as, "login", "yes") == -1) {
		Debug("auth_setoption() failed.\n");
		login_close(lc);
		bzero(greet->password, strlen(greet->password));
		return 0;
	}

	/* Set up state for no challenge, just check a response. */
	auth_setstate(as, 0);
	auth_setdata(as, "", 1);
	auth_setdata(as, greet->password, strlen(greet->password) + 1);

	/* Build path of the auth script and call it */
	snprintf(path, sizeof(path), _PATH_AUTHPROG "%s", style);
	auth_call(as, path, style, "-s", "response", greet->name, 
		  lc->lc_class, (void *)NULL);
	authok = auth_getstate(as);

	if ((authok & AUTH_ALLOW) == 0) {
		Debug("password verify failed\n");
		bzero(greet->password, strlen(greet->password));
		auth_close(as);
		login_close(lc);
		return 0;
	}
	/* Run the approval script */
	if (!auth_approval(as, lc, greet->name, "auth-xdm")) {
		Debug("login not approved\n");
		bzero(greet->password, strlen(greet->password));
		auth_close(as);
		login_close(lc);
		return 0;
	}
	auth_close(as);
	login_close(lc);
	/* Check empty passwords against allowNullPasswd */
	if (!greet->allow_null_passwd && strlen(greet->password) == 0) {
		Debug("empty password not allowed\n");
		return 0;
	}
	/* Only accept root logins if allowRootLogin resource is set */
	if (p->pw_uid == 0 && !greet->allow_root_login) {
		Debug("root logins not allowed\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}

	/*
	 * Shell must be in /etc/shells 
	 */
	for (;;) {
		s = getusershell();
		if (s == NULL) {
			/* did not found the shell in /etc/shells 
			   -> failure */
			Debug("shell not in /etc/shells\n");
			bzero(greet->password, strlen(greet->password));
			endusershell();
			return 0;
		}
		if (strcmp(s, p->pw_shell) == 0) {
			/* found the shell in /etc/shells */
			endusershell();
			break;
		}
	} 
#else /* !USE_BSDAUTH */
int
Verify (struct display *d, struct greet_info *greet, struct verify_info *verify)
{
	struct passwd	*p;
#ifdef USE_PAM
	pam_handle_t **pamhp = thepamhp();
#else
#ifdef USESHADOW
	struct spwd	*sp;
#endif
	char		*user_pass = NULL;
#endif
#ifdef __OpenBSD__
	char            *s;
	struct timeval  tp;
#endif
	char		*shell, *home;
	char		**argv;

	Debug ("Verify %s ...\n", greet->name);

#if defined(sun) && defined(SVR4)
	/* Solaris: If CONSOLE is set to /dev/console in /etc/default/login, 
	   then root can only login on system console */

# define SOLARIS_LOGIN_DEFAULTS "/etc/default/login"

	if (strcmp(greet->name, "root") == 0) {
	    char *console = NULL, *tmp = NULL;
	    FILE *fs;

	    if ((fs= fopen(SOLARIS_LOGIN_DEFAULTS, "r")) != NULL)
	    {   
		char str[120];
		while (!feof(fs))
		{
		    fgets(str, 120, fs);
		    if(str[0] == '#' || strlen(str) < 8)
			continue;
		    if((tmp = strstr(str, "CONSOLE=")) != NULL)
			console = strdup((tmp+8));
		}
		fclose(fs);
                if ( console != NULL && 
		  (strncmp(console, "/dev/console", 12) == 0) && 
		  (strncmp(d->name,":0",2) != 0) )
		{
                        Debug("Not on system console\n");
                        bzero(greet->password, strlen(greet->password));
             		XFree(console); 
	                return 0;
                }
		XFree(console);	
	    }
	    else
	    {
		Debug("Could not open %s\n", SOLARIS_LOGIN_DEFAULTS);
	    }	
	}
#endif    

#ifndef USE_PAM
	p = getpwnam (greet->name);
	endpwent();

	if (!p || strlen (greet->name) == 0) {
		Debug ("getpwnam() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	} else {
#ifdef linux
	    if (!strcmp(p->pw_passwd, "!") || !strcmp(p->pw_passwd, "*")) {
		Debug ("The account is locked, no login allowed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	    }
#endif
	    user_pass = p->pw_passwd;
	}
#endif
#ifdef KERBEROS
	if(strcmp(greet->name, "root") != 0){
		char name[ANAME_SZ];
		char realm[REALM_SZ];
		char *q;
		int ret;
	    
		if(krb_get_lrealm(realm, 1)){
			Debug ("Can't get Kerberos realm.\n");
		} else {

		    sprintf(krbtkfile, "%s.%s", TKT_ROOT, d->name);
		    krb_set_tkt_string(krbtkfile);
		    unlink(krbtkfile);
           
		    ret = krb_verify_user(greet->name, "", realm, 
				      greet->password, 1, "rcmd");
           
		    if(ret == KSUCCESS){
			    chown(krbtkfile, p->pw_uid, p->pw_gid);
			    Debug("kerberos verify succeeded\n");
			    if (k_hasafs()) {
				    if (k_setpag() == -1)
					    LogError ("setpag() failed for %s\n",
						      greet->name);
				    
				    if((ret = k_afsklog(NULL, NULL)) != KSUCCESS)
					    LogError("Warning %s\n", 
						     krb_get_err_text(ret));
			    }
			    goto done;
		    } else if(ret != KDC_PR_UNKNOWN && ret != SKDC_CANT){
			    /* failure */
			    Debug("kerberos verify failure %d\n", ret);
			    krbtkfile[0] = '\0';
		    }
		}
	}
#endif
#ifndef USE_PAM
#ifdef USESHADOW
	errno = 0;
	sp = getspnam(greet->name);
	if (sp == NULL) {
	    Debug ("getspnam() failed, errno=%d.  Are you root?\n", errno);
	} else {
	    user_pass = sp->sp_pwdp;
	}
#ifndef QNX4
	endspent();
#endif  /* QNX4 doesn't need endspent() to end shadow passwd ops */
#endif
#if defined(ultrix) || defined(__ultrix__)
	if (authenticate_user(p, greet->password, NULL) < 0)
#else
	if (strcmp (crypt (greet->password, user_pass), user_pass))
#endif
	{
		if(!greet->allow_null_passwd || strlen(p->pw_passwd) > 0) {
			Debug ("password verify failed\n");
			bzero(greet->password, strlen(greet->password));
			return 0;
		} /* else: null passwd okay */
	}
#ifdef KERBEROS
done:
#endif
#ifdef __OpenBSD__
	/*
	 * Only accept root logins if allowRootLogin resource is set
	 */
	if ((p->pw_uid == 0) && !greet->allow_root_login) {
		Debug("root logins not allowed\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}
	/*
	 * Shell must be in /etc/shells 
	 */
	for (;;) {
		s = getusershell();
		if (s == NULL) {
			/* did not found the shell in /etc/shells 
			   -> failure */
			Debug("shell not in /etc/shells\n");
			bzero(greet->password, strlen(greet->password));
			endusershell();
			return 0;
		}
		if (strcmp(s, p->pw_shell) == 0) {
			/* found the shell in /etc/shells */
			endusershell();
			break;
		}
	} 
	/*
	 * Test for expired password
	 */
	if (p->pw_change || p->pw_expire)
		(void)gettimeofday(&tp, (struct timezone *)NULL);
	if (p->pw_change) {
		if (tp.tv_sec >= p->pw_change) {
			Debug("Password has expired.\n");
			bzero(greet->password, strlen(greet->password));
			return 0;
		}
	}
	if (p->pw_expire) {
		if (tp.tv_sec >= p->pw_expire) {
			Debug("account has expired.\n");
			bzero(greet->password, strlen(greet->password));
			return 0;
		} 
	}
#endif /* __OpenBSD__ */
	bzero(user_pass, strlen(user_pass)); /* in case shadow password */

#else /* USE_PAM */
#define PAM_BAIL	\
	if (pam_error != PAM_SUCCESS) goto pam_failed;

	PAM_password = greet->password;
	pam_error = pam_start("xdm", greet->name, &PAM_conversation, pamhp);
	PAM_BAIL;
	pam_error = pam_set_item(*pamhp, PAM_TTY, d->name);
	PAM_BAIL;
	pam_error = pam_set_item(*pamhp, PAM_RHOST, "");
	PAM_BAIL;
	pam_error = pam_authenticate(*pamhp, 0);
	PAM_BAIL;
	pam_error = pam_acct_mgmt(*pamhp, 0);
	/* really should do password changing, but it doesn't fit well */
	PAM_BAIL;
	pam_error = pam_setcred(*pamhp, 0);
	PAM_BAIL;
	p = getpwnam (greet->name);
	endpwent();

	if (!p || strlen (greet->name) == 0) {
		Debug ("getpwnam() failed.\n");
		bzero(greet->password, strlen(greet->password));
		return 0;
	}

	if (pam_error != PAM_SUCCESS) {
	pam_failed:
		pam_end(*pamhp, PAM_SUCCESS);
		*pamhp = NULL;
		return 0;
	}
#undef PAM_BAIL
#endif /* USE_PAM */
#endif /* USE_BSDAUTH */

	Debug ("verify succeeded\n");
	/* The password is passed to StartClient() for use by user-based
	   authorization schemes.  It is zeroed there. */
	verify->uid = p->pw_uid;
	verify->gid = p->pw_gid;
	home = p->pw_dir;
	shell = p->pw_shell;
	argv = 0;
	if (d->session)
		argv = parseArgs (argv, d->session);
	if (greet->string)
		argv = parseArgs (argv, greet->string);
	if (!argv)
		argv = parseArgs (argv, "xsession");
	verify->argv = argv;
	verify->userEnviron = userEnv (d, p->pw_uid == 0,
				       greet->name, home, shell);
	Debug ("user environment:\n");
	printEnv (verify->userEnviron);
	verify->systemEnviron = systemEnv (d, greet->name, home);
	Debug ("system environment:\n");
	printEnv (verify->systemEnviron);
	Debug ("end of environments\n");
	return 1;
}