Changeset View
Changeset View
Standalone View
Standalone View
sys/rpc/rpcsec_gss/svc_rpcsec_gss.c
Show First 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | |||||
}; | }; | ||||
struct sx svc_rpc_gss_lock; | struct sx svc_rpc_gss_lock; | ||||
struct svc_rpc_gss_callback { | struct svc_rpc_gss_callback { | ||||
SLIST_ENTRY(svc_rpc_gss_callback) cb_link; | SLIST_ENTRY(svc_rpc_gss_callback) cb_link; | ||||
rpc_gss_callback_t cb_callback; | rpc_gss_callback_t cb_callback; | ||||
}; | }; | ||||
static SLIST_HEAD(svc_rpc_gss_callback_list, svc_rpc_gss_callback) | SLIST_HEAD(svc_rpc_gss_callback_list, svc_rpc_gss_callback); | ||||
svc_rpc_gss_callbacks = SLIST_HEAD_INITIALIZER(svc_rpc_gss_callbacks); | KGSS_VNET_DEFINE_STATIC(struct svc_rpc_gss_callback_list, | ||||
svc_rpc_gss_callbacks) = SLIST_HEAD_INITIALIZER(svc_rpc_gss_callbacks); | |||||
struct svc_rpc_gss_svc_name { | struct svc_rpc_gss_svc_name { | ||||
SLIST_ENTRY(svc_rpc_gss_svc_name) sn_link; | SLIST_ENTRY(svc_rpc_gss_svc_name) sn_link; | ||||
char *sn_principal; | char *sn_principal; | ||||
gss_OID sn_mech; | gss_OID sn_mech; | ||||
u_int sn_req_time; | u_int sn_req_time; | ||||
gss_cred_id_t sn_cred; | gss_cred_id_t sn_cred; | ||||
u_int sn_program; | u_int sn_program; | ||||
u_int sn_version; | u_int sn_version; | ||||
}; | }; | ||||
static SLIST_HEAD(svc_rpc_gss_svc_name_list, svc_rpc_gss_svc_name) | SLIST_HEAD(svc_rpc_gss_svc_name_list, svc_rpc_gss_svc_name); | ||||
svc_rpc_gss_svc_names = SLIST_HEAD_INITIALIZER(svc_rpc_gss_svc_names); | KGSS_VNET_DEFINE_STATIC(struct svc_rpc_gss_svc_name_list, | ||||
svc_rpc_gss_svc_names) = SLIST_HEAD_INITIALIZER(svc_rpc_gss_svc_names); | |||||
enum svc_rpc_gss_client_state { | enum svc_rpc_gss_client_state { | ||||
CLIENT_NEW, /* still authenticating */ | CLIENT_NEW, /* still authenticating */ | ||||
CLIENT_ESTABLISHED, /* context established */ | CLIENT_ESTABLISHED, /* context established */ | ||||
CLIENT_STALE /* garbage to collect */ | CLIENT_STALE /* garbage to collect */ | ||||
}; | }; | ||||
#define SVC_RPC_GSS_SEQWINDOW 128 | #define SVC_RPC_GSS_SEQWINDOW 128 | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | SYSCTL_UINT(_kern_rpc_gss, OID_AUTO, lifetime_max, CTLFLAG_RW, | ||||
&svc_rpc_gss_lifetime_max, 0, | &svc_rpc_gss_lifetime_max, 0, | ||||
"Maximum lifetime (seconds) of rpc-gss clients"); | "Maximum lifetime (seconds) of rpc-gss clients"); | ||||
static u_int svc_rpc_gss_client_count; | static u_int svc_rpc_gss_client_count; | ||||
SYSCTL_UINT(_kern_rpc_gss, OID_AUTO, client_count, CTLFLAG_RD, | SYSCTL_UINT(_kern_rpc_gss, OID_AUTO, client_count, CTLFLAG_RD, | ||||
&svc_rpc_gss_client_count, 0, | &svc_rpc_gss_client_count, 0, | ||||
"Number of rpc-gss clients"); | "Number of rpc-gss clients"); | ||||
struct svc_rpc_gss_client_list *svc_rpc_gss_client_hash; | KGSS_VNET_DEFINE(struct svc_rpc_gss_client_list *, svc_rpc_gss_client_hash); | ||||
struct svc_rpc_gss_client_list svc_rpc_gss_clients; | KGSS_VNET_DEFINE(struct svc_rpc_gss_client_list, svc_rpc_gss_clients); | ||||
static uint32_t svc_rpc_gss_next_clientid = 1; | KGSS_VNET_DEFINE_STATIC(uint32_t, svc_rpc_gss_next_clientid) = 1; | ||||
static void | static void | ||||
svc_rpc_gss_init(void *arg) | svc_rpc_gss_init(void *arg) | ||||
{ | { | ||||
int i; | int i; | ||||
svc_rpc_gss_client_hash = mem_alloc(sizeof(struct svc_rpc_gss_client_list) * svc_rpc_gss_client_hash_size); | KGSS_VNET(svc_rpc_gss_client_hash) = mem_alloc( | ||||
sizeof(struct svc_rpc_gss_client_list) * | |||||
svc_rpc_gss_client_hash_size); | |||||
for (i = 0; i < svc_rpc_gss_client_hash_size; i++) | for (i = 0; i < svc_rpc_gss_client_hash_size; i++) | ||||
TAILQ_INIT(&svc_rpc_gss_client_hash[i]); | TAILQ_INIT(&KGSS_VNET(svc_rpc_gss_client_hash)[i]); | ||||
TAILQ_INIT(&svc_rpc_gss_clients); | TAILQ_INIT(&KGSS_VNET(svc_rpc_gss_clients)); | ||||
if (IS_DEFAULT_VNET(curvnet)) { | |||||
svc_auth_reg(RPCSEC_GSS, svc_rpc_gss, rpc_gss_svc_getcred); | svc_auth_reg(RPCSEC_GSS, svc_rpc_gss, rpc_gss_svc_getcred); | ||||
sx_init(&svc_rpc_gss_lock, "gsslock"); | sx_init(&svc_rpc_gss_lock, "gsslock"); | ||||
} | } | ||||
SYSINIT(svc_rpc_gss_init, SI_SUB_KMEM, SI_ORDER_ANY, svc_rpc_gss_init, NULL); | } | ||||
VNET_SYSINIT(svc_rpc_gss_init, SI_SUB_VNET_DONE, SI_ORDER_ANY, | |||||
svc_rpc_gss_init, NULL); | |||||
/* Osd entry for prison cleanup. */ | |||||
int | |||||
rpcgss_prison_cleanup(void *obj, void *data __unused) | |||||
{ | |||||
struct prison *pr = obj; | |||||
if ((pr->pr_flags & PR_VNET) == 0) | |||||
return (0); | |||||
KGSS_CURVNET_SET(pr->pr_vnet); | |||||
free(KGSS_VNET(svc_rpc_gss_client_hash), M_RPC); | |||||
KGSS_CURVNET_RESTORE(); | |||||
return (0); | |||||
} | |||||
bool_t | bool_t | ||||
rpc_gss_set_callback(rpc_gss_callback_t *cb) | rpc_gss_set_callback(rpc_gss_callback_t *cb) | ||||
{ | { | ||||
struct svc_rpc_gss_callback *scb; | struct svc_rpc_gss_callback *scb; | ||||
scb = mem_alloc(sizeof(struct svc_rpc_gss_callback)); | scb = mem_alloc(sizeof(struct svc_rpc_gss_callback)); | ||||
if (!scb) { | if (!scb) { | ||||
_rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM); | _rpc_gss_set_error(RPC_GSS_ER_SYSTEMERROR, ENOMEM); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
scb->cb_callback = *cb; | scb->cb_callback = *cb; | ||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
SLIST_INSERT_HEAD(&svc_rpc_gss_callbacks, scb, cb_link); | SLIST_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_callbacks), scb, cb_link); | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
void | void | ||||
rpc_gss_clear_callback(rpc_gss_callback_t *cb) | rpc_gss_clear_callback(rpc_gss_callback_t *cb) | ||||
{ | { | ||||
struct svc_rpc_gss_callback *scb; | struct svc_rpc_gss_callback *scb; | ||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
SLIST_FOREACH(scb, &svc_rpc_gss_callbacks, cb_link) { | SLIST_FOREACH(scb, &KGSS_VNET(svc_rpc_gss_callbacks), cb_link) { | ||||
if (scb->cb_callback.program == cb->program | if (scb->cb_callback.program == cb->program | ||||
&& scb->cb_callback.version == cb->version | && scb->cb_callback.version == cb->version | ||||
&& scb->cb_callback.callback == cb->callback) { | && scb->cb_callback.callback == cb->callback) { | ||||
SLIST_REMOVE(&svc_rpc_gss_callbacks, scb, | SLIST_REMOVE(&KGSS_VNET(svc_rpc_gss_callbacks), scb, | ||||
svc_rpc_gss_callback, cb_link); | svc_rpc_gss_callback, cb_link); | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
mem_free(scb, sizeof(*scb)); | mem_free(scb, sizeof(*scb)); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | rpc_gss_set_svc_name(const char *principal, const char *mechanism, | ||||
if (!rpc_gss_acquire_svc_cred(sname)) { | if (!rpc_gss_acquire_svc_cred(sname)) { | ||||
free(sname->sn_principal, M_RPC); | free(sname->sn_principal, M_RPC); | ||||
mem_free(sname, sizeof(*sname)); | mem_free(sname, sizeof(*sname)); | ||||
return (FALSE); | return (FALSE); | ||||
} | } | ||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
SLIST_INSERT_HEAD(&svc_rpc_gss_svc_names, sname, sn_link); | SLIST_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_svc_names), sname, sn_link); | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
void | void | ||||
rpc_gss_clear_svc_name(u_int program, u_int version) | rpc_gss_clear_svc_name(u_int program, u_int version) | ||||
{ | { | ||||
OM_uint32 min_stat; | OM_uint32 min_stat; | ||||
struct svc_rpc_gss_svc_name *sname; | struct svc_rpc_gss_svc_name *sname; | ||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
SLIST_FOREACH(sname, &svc_rpc_gss_svc_names, sn_link) { | SLIST_FOREACH(sname, &KGSS_VNET(svc_rpc_gss_svc_names), sn_link) { | ||||
if (sname->sn_program == program | if (sname->sn_program == program | ||||
&& sname->sn_version == version) { | && sname->sn_version == version) { | ||||
SLIST_REMOVE(&svc_rpc_gss_svc_names, sname, | SLIST_REMOVE(&KGSS_VNET(svc_rpc_gss_svc_names), sname, | ||||
svc_rpc_gss_svc_name, sn_link); | svc_rpc_gss_svc_name, sn_link); | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
gss_release_cred(&min_stat, &sname->sn_cred); | gss_release_cred(&min_stat, &sname->sn_cred); | ||||
free(sname->sn_principal, M_RPC); | free(sname->sn_principal, M_RPC); | ||||
mem_free(sname, sizeof(*sname)); | mem_free(sname, sizeof(*sname)); | ||||
return; | return; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 131 Lines • ▼ Show 20 Lines | if (client->cl_cred) { | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
uc = &client->cl_ucred; | uc = &client->cl_ucred; | ||||
cr = client->cl_cred = crget(); | cr = client->cl_cred = crget(); | ||||
cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid; | cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid; | ||||
cr->cr_rgid = cr->cr_svgid = uc->gid; | cr->cr_rgid = cr->cr_svgid = uc->gid; | ||||
crsetgroups(cr, uc->gidlen, uc->gidlist); | crsetgroups(cr, uc->gidlen, uc->gidlist); | ||||
#ifdef VNET_NFSD | |||||
if (jailed(curthread->td_ucred)) | if (jailed(curthread->td_ucred)) | ||||
cr->cr_prison = curthread->td_ucred->cr_prison; | cr->cr_prison = curthread->td_ucred->cr_prison; | ||||
else | else | ||||
#endif | |||||
cr->cr_prison = &prison0; | cr->cr_prison = &prison0; | ||||
prison_hold(cr->cr_prison); | prison_hold(cr->cr_prison); | ||||
*crp = crhold(cr); | *crp = crhold(cr); | ||||
return (TRUE); | return (TRUE); | ||||
} | } | ||||
int | int | ||||
▲ Show 20 Lines • Show All 49 Lines • ▼ Show 20 Lines | svc_rpc_gss_find_client(struct svc_rpc_gss_clientid *id) | ||||
rpc_gss_log_debug("in svc_rpc_gss_find_client(%d)", id->ci_id); | rpc_gss_log_debug("in svc_rpc_gss_find_client(%d)", id->ci_id); | ||||
getcredhostid(curthread->td_ucred, &hostid); | getcredhostid(curthread->td_ucred, &hostid); | ||||
getboottime(&boottime); | getboottime(&boottime); | ||||
if (id->ci_hostid != hostid || id->ci_boottime != boottime.tv_sec) | if (id->ci_hostid != hostid || id->ci_boottime != boottime.tv_sec) | ||||
return (NULL); | return (NULL); | ||||
list = &svc_rpc_gss_client_hash[id->ci_id % svc_rpc_gss_client_hash_size]; | list = &KGSS_VNET(svc_rpc_gss_client_hash) | ||||
[id->ci_id % svc_rpc_gss_client_hash_size]; | |||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
TAILQ_FOREACH(client, list, cl_link) { | TAILQ_FOREACH(client, list, cl_link) { | ||||
if (client->cl_id.ci_id == id->ci_id) { | if (client->cl_id.ci_id == id->ci_id) { | ||||
/* | /* | ||||
* Move this client to the front of the LRU | * Move this client to the front of the LRU | ||||
* list. | * list. | ||||
*/ | */ | ||||
TAILQ_REMOVE(&svc_rpc_gss_clients, client, cl_alllink); | TAILQ_REMOVE(&KGSS_VNET(svc_rpc_gss_clients), client, | ||||
TAILQ_INSERT_HEAD(&svc_rpc_gss_clients, client, | |||||
cl_alllink); | cl_alllink); | ||||
TAILQ_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_clients), | |||||
client, cl_alllink); | |||||
refcount_acquire(&client->cl_refs); | refcount_acquire(&client->cl_refs); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
return (client); | return (client); | ||||
} | } | ||||
Show All 16 Lines | svc_rpc_gss_create_client(void) | ||||
* and the other to hold onto the client structure until it expires. | * and the other to hold onto the client structure until it expires. | ||||
*/ | */ | ||||
refcount_init(&client->cl_refs, 2); | refcount_init(&client->cl_refs, 2); | ||||
sx_init(&client->cl_lock, "GSS-client"); | sx_init(&client->cl_lock, "GSS-client"); | ||||
getcredhostid(curthread->td_ucred, &hostid); | getcredhostid(curthread->td_ucred, &hostid); | ||||
client->cl_id.ci_hostid = hostid; | client->cl_id.ci_hostid = hostid; | ||||
getboottime(&boottime); | getboottime(&boottime); | ||||
client->cl_id.ci_boottime = boottime.tv_sec; | client->cl_id.ci_boottime = boottime.tv_sec; | ||||
client->cl_id.ci_id = svc_rpc_gss_next_clientid++; | client->cl_id.ci_id = KGSS_VNET(svc_rpc_gss_next_clientid)++; | ||||
/* | /* | ||||
* Start the client off with a short expiration time. We will | * Start the client off with a short expiration time. We will | ||||
* try to get a saner value from the client creds later. | * try to get a saner value from the client creds later. | ||||
*/ | */ | ||||
client->cl_state = CLIENT_NEW; | client->cl_state = CLIENT_NEW; | ||||
client->cl_locked = FALSE; | client->cl_locked = FALSE; | ||||
client->cl_expiration = time_uptime + 5*60; | client->cl_expiration = time_uptime + 5*60; | ||||
list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; | list = &KGSS_VNET(svc_rpc_gss_client_hash) | ||||
[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; | |||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
TAILQ_INSERT_HEAD(list, client, cl_link); | TAILQ_INSERT_HEAD(list, client, cl_link); | ||||
TAILQ_INSERT_HEAD(&svc_rpc_gss_clients, client, cl_alllink); | TAILQ_INSERT_HEAD(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink); | ||||
svc_rpc_gss_client_count++; | svc_rpc_gss_client_count++; | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
return (client); | return (client); | ||||
} | } | ||||
static void | static void | ||||
svc_rpc_gss_destroy_client(struct svc_rpc_gss_client *client) | svc_rpc_gss_destroy_client(struct svc_rpc_gss_client *client) | ||||
{ | { | ||||
Show All 37 Lines | |||||
* Must be called with svc_rpc_gss_lock held. | * Must be called with svc_rpc_gss_lock held. | ||||
*/ | */ | ||||
static void | static void | ||||
svc_rpc_gss_forget_client_locked(struct svc_rpc_gss_client *client) | svc_rpc_gss_forget_client_locked(struct svc_rpc_gss_client *client) | ||||
{ | { | ||||
struct svc_rpc_gss_client_list *list; | struct svc_rpc_gss_client_list *list; | ||||
sx_assert(&svc_rpc_gss_lock, SX_XLOCKED); | sx_assert(&svc_rpc_gss_lock, SX_XLOCKED); | ||||
list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; | list = &KGSS_VNET(svc_rpc_gss_client_hash) | ||||
[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; | |||||
TAILQ_REMOVE(list, client, cl_link); | TAILQ_REMOVE(list, client, cl_link); | ||||
TAILQ_REMOVE(&svc_rpc_gss_clients, client, cl_alllink); | TAILQ_REMOVE(&KGSS_VNET(svc_rpc_gss_clients), client, cl_alllink); | ||||
svc_rpc_gss_client_count--; | svc_rpc_gss_client_count--; | ||||
} | } | ||||
/* | /* | ||||
* Remove a client from our global lists and free it if we can. | * Remove a client from our global lists and free it if we can. | ||||
*/ | */ | ||||
static void | static void | ||||
svc_rpc_gss_forget_client(struct svc_rpc_gss_client *client) | svc_rpc_gss_forget_client(struct svc_rpc_gss_client *client) | ||||
{ | { | ||||
struct svc_rpc_gss_client_list *list; | struct svc_rpc_gss_client_list *list; | ||||
struct svc_rpc_gss_client *tclient; | struct svc_rpc_gss_client *tclient; | ||||
list = &svc_rpc_gss_client_hash[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; | list = &KGSS_VNET(svc_rpc_gss_client_hash) | ||||
[client->cl_id.ci_id % svc_rpc_gss_client_hash_size]; | |||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
TAILQ_FOREACH(tclient, list, cl_link) { | TAILQ_FOREACH(tclient, list, cl_link) { | ||||
/* | /* | ||||
* Make sure this client has not already been removed | * Make sure this client has not already been removed | ||||
* from the lists by svc_rpc_gss_forget_client() or | * from the lists by svc_rpc_gss_forget_client() or | ||||
* svc_rpc_gss_forget_client_locked(). | * svc_rpc_gss_forget_client_locked(). | ||||
*/ | */ | ||||
if (client == tclient) { | if (client == tclient) { | ||||
Show All 14 Lines | svc_rpc_gss_timeout_clients(void) | ||||
rpc_gss_log_debug("in svc_rpc_gss_timeout_clients()"); | rpc_gss_log_debug("in svc_rpc_gss_timeout_clients()"); | ||||
/* | /* | ||||
* First enforce the max client limit. We keep | * First enforce the max client limit. We keep | ||||
* svc_rpc_gss_clients in LRU order. | * svc_rpc_gss_clients in LRU order. | ||||
*/ | */ | ||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
client = TAILQ_LAST(&svc_rpc_gss_clients, svc_rpc_gss_client_list); | client = TAILQ_LAST(&KGSS_VNET(svc_rpc_gss_clients), | ||||
svc_rpc_gss_client_list); | |||||
while (svc_rpc_gss_client_count > svc_rpc_gss_client_max && client != NULL) { | while (svc_rpc_gss_client_count > svc_rpc_gss_client_max && client != NULL) { | ||||
svc_rpc_gss_forget_client_locked(client); | svc_rpc_gss_forget_client_locked(client); | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
svc_rpc_gss_release_client(client); | svc_rpc_gss_release_client(client); | ||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
client = TAILQ_LAST(&svc_rpc_gss_clients, | client = TAILQ_LAST(&KGSS_VNET(svc_rpc_gss_clients), | ||||
svc_rpc_gss_client_list); | svc_rpc_gss_client_list); | ||||
} | } | ||||
again: | again: | ||||
TAILQ_FOREACH(client, &svc_rpc_gss_clients, cl_alllink) { | TAILQ_FOREACH(client, &KGSS_VNET(svc_rpc_gss_clients), cl_alllink) { | ||||
if (client->cl_state == CLIENT_STALE | if (client->cl_state == CLIENT_STALE | ||||
|| now > client->cl_expiration) { | || now > client->cl_expiration) { | ||||
svc_rpc_gss_forget_client_locked(client); | svc_rpc_gss_forget_client_locked(client); | ||||
sx_xunlock(&svc_rpc_gss_lock); | sx_xunlock(&svc_rpc_gss_lock); | ||||
rpc_gss_log_debug("expiring client %p", client); | rpc_gss_log_debug("expiring client %p", client); | ||||
svc_rpc_gss_release_client(client); | svc_rpc_gss_release_client(client); | ||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
goto again; | goto again; | ||||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | svc_rpc_gss_accept_sec_context(struct svc_rpc_gss_client *client, | ||||
} | } | ||||
/* | /* | ||||
* First time round, try all the server names we have until | * First time round, try all the server names we have until | ||||
* one matches. Afterwards, stick with that one. | * one matches. Afterwards, stick with that one. | ||||
*/ | */ | ||||
sx_xlock(&svc_rpc_gss_lock); | sx_xlock(&svc_rpc_gss_lock); | ||||
if (!client->cl_sname) { | if (!client->cl_sname) { | ||||
SLIST_FOREACH(sname, &svc_rpc_gss_svc_names, sn_link) { | SLIST_FOREACH(sname, &KGSS_VNET(svc_rpc_gss_svc_names), | ||||
sn_link) { | |||||
if (sname->sn_program == rqst->rq_prog | if (sname->sn_program == rqst->rq_prog | ||||
&& sname->sn_version == rqst->rq_vers) { | && sname->sn_version == rqst->rq_vers) { | ||||
retry: | retry: | ||||
gr->gr_major = gss_accept_sec_context( | gr->gr_major = gss_accept_sec_context( | ||||
&gr->gr_minor, | &gr->gr_minor, | ||||
&client->cl_ctx, | &client->cl_ctx, | ||||
sname->sn_cred, | sname->sn_cred, | ||||
&recv_tok, | &recv_tok, | ||||
▲ Show 20 Lines • Show All 237 Lines • ▼ Show 20 Lines | svc_rpc_gss_callback(struct svc_rpc_gss_client *client, struct svc_req *rqst) | ||||
void *cookie; | void *cookie; | ||||
bool_t cb_res; | bool_t cb_res; | ||||
bool_t result; | bool_t result; | ||||
/* | /* | ||||
* See if we have a callback for this guy. | * See if we have a callback for this guy. | ||||
*/ | */ | ||||
result = TRUE; | result = TRUE; | ||||
SLIST_FOREACH(scb, &svc_rpc_gss_callbacks, cb_link) { | SLIST_FOREACH(scb, &KGSS_VNET(svc_rpc_gss_callbacks), cb_link) { | ||||
if (scb->cb_callback.program == rqst->rq_prog | if (scb->cb_callback.program == rqst->rq_prog | ||||
&& scb->cb_callback.version == rqst->rq_vers) { | && scb->cb_callback.version == rqst->rq_vers) { | ||||
/* | /* | ||||
* This one matches. Call the callback and see | * This one matches. Call the callback and see | ||||
* if it wants to veto or something. | * if it wants to veto or something. | ||||
*/ | */ | ||||
lock.locked = FALSE; | lock.locked = FALSE; | ||||
lock.raw_cred = &client->cl_rawcred; | lock.raw_cred = &client->cl_rawcred; | ||||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | svc_rpc_gss(struct svc_req *rqst, struct rpc_msg *msg) | ||||
struct svc_rpc_gss_cookedcred *cc; | struct svc_rpc_gss_cookedcred *cc; | ||||
struct svc_rpc_gss_client *client; | struct svc_rpc_gss_client *client; | ||||
struct rpc_gss_cred gc; | struct rpc_gss_cred gc; | ||||
struct rpc_gss_init_res gr; | struct rpc_gss_init_res gr; | ||||
gss_qop_t qop; | gss_qop_t qop; | ||||
int call_stat; | int call_stat; | ||||
enum auth_stat result; | enum auth_stat result; | ||||
KGSS_CURVNET_SET_QUIET(KGSS_TD_TO_VNET(curthread)); | |||||
rpc_gss_log_debug("in svc_rpc_gss()"); | rpc_gss_log_debug("in svc_rpc_gss()"); | ||||
/* Garbage collect old clients. */ | /* Garbage collect old clients. */ | ||||
svc_rpc_gss_timeout_clients(); | svc_rpc_gss_timeout_clients(); | ||||
/* Initialize reply. */ | /* Initialize reply. */ | ||||
rqst->rq_verf = _null_auth; | rqst->rq_verf = _null_auth; | ||||
/* Deserialize client credentials. */ | /* Deserialize client credentials. */ | ||||
if (rqst->rq_cred.oa_length <= 0) | if (rqst->rq_cred.oa_length <= 0) { | ||||
KGSS_CURVNET_RESTORE(); | |||||
return (AUTH_BADCRED); | return (AUTH_BADCRED); | ||||
} | |||||
memset(&gc, 0, sizeof(gc)); | memset(&gc, 0, sizeof(gc)); | ||||
xdrmem_create(&xdrs, rqst->rq_cred.oa_base, | xdrmem_create(&xdrs, rqst->rq_cred.oa_base, | ||||
rqst->rq_cred.oa_length, XDR_DECODE); | rqst->rq_cred.oa_length, XDR_DECODE); | ||||
if (!xdr_rpc_gss_cred(&xdrs, &gc)) { | if (!xdr_rpc_gss_cred(&xdrs, &gc)) { | ||||
XDR_DESTROY(&xdrs); | XDR_DESTROY(&xdrs); | ||||
KGSS_CURVNET_RESTORE(); | |||||
return (AUTH_BADCRED); | return (AUTH_BADCRED); | ||||
} | } | ||||
XDR_DESTROY(&xdrs); | XDR_DESTROY(&xdrs); | ||||
client = NULL; | client = NULL; | ||||
/* Check version. */ | /* Check version. */ | ||||
if (gc.gc_version != RPCSEC_GSS_VERSION) { | if (gc.gc_version != RPCSEC_GSS_VERSION) { | ||||
▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | default: | ||||
result = AUTH_BADCRED; | result = AUTH_BADCRED; | ||||
break; | break; | ||||
} | } | ||||
out: | out: | ||||
if (client) | if (client) | ||||
svc_rpc_gss_release_client(client); | svc_rpc_gss_release_client(client); | ||||
xdr_free((xdrproc_t) xdr_rpc_gss_cred, (char *) &gc); | xdr_free((xdrproc_t) xdr_rpc_gss_cred, (char *) &gc); | ||||
KGSS_CURVNET_RESTORE(); | |||||
return (result); | return (result); | ||||
} | } | ||||
static bool_t | static bool_t | ||||
svc_rpc_gss_wrap(SVCAUTH *auth, struct mbuf **mp) | svc_rpc_gss_wrap(SVCAUTH *auth, struct mbuf **mp) | ||||
{ | { | ||||
struct svc_rpc_gss_cookedcred *cc; | struct svc_rpc_gss_cookedcred *cc; | ||||
struct svc_rpc_gss_client *client; | struct svc_rpc_gss_client *client; | ||||
▲ Show 20 Lines • Show All 47 Lines • Show Last 20 Lines |