FreeBSD/sys/rpc/rpcsec_gss/rpcsec_gss.c
/*
 * Simplified interface to create a security association for the
 * current thread's * ucred.
 */
Simplified interface to create a security association for the
current thread's * ucred.
Simplified interface to create a security association for the current thread ' s * ucred .
AUTH *
rpc_gss_secfind(CLIENT *clnt, struct ucred *cred, const char *principal,
    gss_OID mech_oid, rpc_gss_service_t service)
{
	uint32_t		h, th;
	AUTH			*auth;
	struct rpc_gss_data	*gd, *tgd;
	rpc_gss_options_ret_t	options;
	if (rpc_gss_count > RPC_GSS_MAX) {
		while (rpc_gss_count > RPC_GSS_MAX) {
			sx_xlock(&rpc_gss_lock);
			tgd = TAILQ_FIRST(&rpc_gss_all);
			th = tgd->gd_hash;
			TAILQ_REMOVE(&rpc_gss_cache[th], tgd, gd_link);
			TAILQ_REMOVE(&rpc_gss_all, tgd, gd_alllink);
			rpc_gss_count--;
			sx_xunlock(&rpc_gss_lock);
			AUTH_DESTROY(tgd->gd_auth);
		}
	}
	h = rpc_gss_hash(principal, mech_oid, cred, service);
again:
	sx_slock(&rpc_gss_lock);
	TAILQ_FOREACH(gd, &rpc_gss_cache[h], gd_link) {
		if (gd->gd_ucred->cr_uid == cred->cr_uid
		    && !strcmp(gd->gd_principal, principal)
		    && gd->gd_mech == mech_oid
		    && gd->gd_cred.gc_svc == service) {
			refcount_acquire(&gd->gd_refs);
			if (sx_try_upgrade(&rpc_gss_lock)) {
				TAILQ_REMOVE(&rpc_gss_all, gd, gd_alllink);
				TAILQ_INSERT_TAIL(&rpc_gss_all, gd,
				    gd_alllink);
				sx_xunlock(&rpc_gss_lock);
			} else {
				sx_sunlock(&rpc_gss_lock);
			}
			if (gd->gd_state != RPCSEC_GSS_ESTABLISHED) {
				memset(&options, 0, sizeof (options));
				(void) rpc_gss_init(gd->gd_auth, &options);
			}
			return (gd->gd_auth);
		}
	}
	sx_sunlock(&rpc_gss_lock);
	auth = rpc_gss_seccreate_int(clnt, cred, NULL, principal, mech_oid,
	    service, GSS_C_QOP_DEFAULT, NULL, NULL);
	if (!auth)
		return (NULL);
	gd = AUTH_PRIVATE(auth);
	gd->gd_hash = h;
	sx_xlock(&rpc_gss_lock);
	TAILQ_FOREACH(tgd, &rpc_gss_cache[h], gd_link) {
		if (tgd->gd_ucred->cr_uid == cred->cr_uid
		    && !strcmp(tgd->gd_principal, principal)
		    && tgd->gd_mech == mech_oid
		    && tgd->gd_cred.gc_svc == service) {
			sx_xunlock(&rpc_gss_lock);
			AUTH_DESTROY(auth);
			goto again;
		}
	}
	rpc_gss_count++;
	TAILQ_INSERT_TAIL(&rpc_gss_cache[h], gd, gd_link);
	TAILQ_INSERT_TAIL(&rpc_gss_all, gd, gd_alllink);
	refcount_acquire(&gd->gd_refs);	
	sx_xunlock(&rpc_gss_lock);
	return (auth);
}
AUTH * rpc_gss_secfind ( CLIENT * clnt , struct ucred * cred , const char * principal , gss_OID mech_oid , rpc_gss_service_t service ) { uint32_t h , th ; AUTH * auth ; struct rpc_gss_data * gd , * tgd ; rpc_gss_options_ret_t options ; if ( rpc_gss_count > RPC_GSS_MAX ) { while ( rpc_gss_count > RPC_GSS_MAX ) { sx_xlock ( & rpc_gss_lock ) ; tgd = TAILQ_FIRST ( & rpc_gss_all ) ; th = tgd -> gd_hash ; TAILQ_REMOVE ( & rpc_gss_cache [ th ] , tgd , gd_link ) ; TAILQ_REMOVE ( & rpc_gss_all , tgd , gd_alllink ) ; rpc_gss_count -- ; sx_xunlock ( & rpc_gss_lock ) ; AUTH_DESTROY ( tgd -> gd_auth ) ; } } h = rpc_gss_hash ( principal , mech_oid , cred , service ) ; again : sx_slock ( & rpc_gss_lock ) ; TAILQ_FOREACH ( gd , & rpc_gss_cache [ h ] , gd_link ) { if ( gd -> gd_ucred -> cr_uid == cred -> cr_uid && ! strcmp ( gd -> gd_principal , principal ) && gd -> gd_mech == mech_oid && gd -> gd_cred . gc_svc == service ) { refcount_acquire ( & gd -> gd_refs ) ; if ( sx_try_upgrade ( & rpc_gss_lock ) ) { TAILQ_REMOVE ( & rpc_gss_all , gd , gd_alllink ) ; TAILQ_INSERT_TAIL ( & rpc_gss_all , gd , gd_alllink ) ; sx_xunlock ( & rpc_gss_lock ) ; } else { sx_sunlock ( & rpc_gss_lock ) ; } if ( gd -> gd_state != RPCSEC_GSS_ESTABLISHED ) { memset ( & options , 0 , sizeof ( options ) ) ; ( void ) rpc_gss_init ( gd -> gd_auth , & options ) ; } return ( gd -> gd_auth ) ; } } sx_sunlock ( & rpc_gss_lock ) ; auth = rpc_gss_seccreate_int ( clnt , cred , NULL , principal , mech_oid , service , GSS_C_QOP_DEFAULT , NULL , NULL ) ; if ( ! auth ) return ( NULL ) ; gd = AUTH_PRIVATE ( auth ) ; gd -> gd_hash = h ; sx_xlock ( & rpc_gss_lock ) ; TAILQ_FOREACH ( tgd , & rpc_gss_cache [ h ] , gd_link ) { if ( tgd -> gd_ucred -> cr_uid == cred -> cr_uid && ! strcmp ( tgd -> gd_principal , principal ) && tgd -> gd_mech == mech_oid && tgd -> gd_cred . gc_svc == service ) { sx_xunlock ( & rpc_gss_lock ) ; AUTH_DESTROY ( auth ) ; goto again ; } } rpc_gss_count ++ ; TAILQ_INSERT_TAIL ( & rpc_gss_cache [ h ] , gd , gd_link ) ; TAILQ_INSERT_TAIL ( & rpc_gss_all , gd , gd_alllink ) ; refcount_acquire ( & gd -> gd_refs ) ; sx_xunlock ( & rpc_gss_lock ) ; return ( auth ) ; }
Simplified interface to create a security association for the
 current thread's * ucred.
Simplified interface to create a security association for the current thread ' s * ucred .
/*
	 * See if we already have an AUTH which matches.
	 */ /*
				 * Keep rpc_gss_all LRU sorted.
				 */ /*
			 * If the state != ESTABLISHED, try and initialize
			 * the authenticator again. This will happen if the
			 * user's credentials have expired. It may succeed now,
			 * if they have done a kinit or similar.
			 */ /*
	 * We missed in the cache - create a new association.
	 */ /*
			 * We lost a race to create the AUTH that
			 * matches this cred.
			 */ /* one for the cache, one for user */