/*ARGSUSED*/ int sec_clnt_revoke(int rpcflavor, uid_t uid, cred_t *cr, void *mechanism, model_t model) { struct desauthent *da; int error = 0; zoneid_t zoneid = getzoneid(); if (uid != crgetuid(cr) && secpolicy_nfs(cr) != 0) return (EPERM); switch (rpcflavor) { case AUTH_DES: mutex_enter(&desauthtab_lock); if (desauthtab != NULL) { for (da = desauthtab; da < &desauthtab[clnt_authdes_cachesz]; da++) { if (uid == da->da_uid && zoneid == da->da_zoneid) revoke_key(da->da_auth, 1); } } mutex_exit(&desauthtab_lock); return (0); case RPCSEC_GSS: { rpc_gss_OID mech; caddr_t elements; if (!mechanism) return (EINVAL); /* copyin the gss mechanism type */ mech = kmem_alloc(sizeof (rpc_gss_OID_desc), KM_SLEEP); #ifdef _SYSCALL32_IMPL if (model != DATAMODEL_NATIVE) { gss_OID_desc32 mech32; if (copyin(mechanism, &mech32, sizeof (gss_OID_desc32))) { kmem_free(mech, sizeof (rpc_gss_OID_desc)); return (EFAULT); } mech->length = mech32.length; mech->elements = (caddr_t)(uintptr_t)mech32.elements; } else #endif /* _SYSCALL32_IMPL */ if (copyin(mechanism, mech, sizeof (rpc_gss_OID_desc))) { kmem_free(mech, sizeof (rpc_gss_OID_desc)); return (EFAULT); } if (mech->length < MINAUTHLEN || mech->length > MAXAUTHLEN) { kmem_free(mech, sizeof (rpc_gss_OID_desc)); return (EINVAL); } elements = kmem_alloc(mech->length, KM_SLEEP); if (copyin(mech->elements, elements, mech->length)) { kmem_free(elements, mech->length); kmem_free(mech, sizeof (rpc_gss_OID_desc)); return (EFAULT); } mech->elements = elements; error = rpc_gss_revauth(uid, mech); kmem_free(elements, mech->length); kmem_free(mech, sizeof (rpc_gss_OID_desc)); return (error); } default: /* not an auth type with cached creds */ return (EINVAL); } }
void * handle_client(void * arg) { struct thread_data_t * datum = (struct thread_data_t *)(arg); /* Fetch the ID from the argument */ #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker started\n", datum->id); #endif /* Worker thread signal handling is unique */ sigaction(SIGUSR1, datum->signal_action, NULL); sigaction(SIGUSR2, datum->signal_action, NULL); /* As long as possible, grab up whatever connection is available */ while (!session_data.caught_signal && !datum->caught_signal) { /* Ensure only one worker accepts the next client */ gcry_pthread_mutex_lock((void **)(&session_data.accept_mutex)); datum->sock = accept(session_data.sock, (struct sockaddr *)(&datum->remote_addr), &datum->remote_addr_len); gcry_pthread_mutex_unlock((void **)(&session_data.accept_mutex)); if (datum->sock >= 0) { #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker connected to client\n", datum->id); #endif /* Receive a "hello" message from the client */ recv_message(&datum->buffet, datum->sock); /* Decrypt it with the default key */ decrypt_message(&datum->buffet, keystore.key); /* Verify it is an authentication request */ if (strncmp(datum->buffet.tbuffer, AUTH_CHECK_MSG, sizeof(AUTH_CHECK_MSG))) { /* Respond with nonce (misdirection) */ gcry_create_nonce(datum->buffet.pbuffer, MAX_COMMAND_LENGTH); encrypt_message(&datum->buffet, keystore.key); send_message(&datum->buffet, datum->sock); } else { /* Request a session key */ gcry_pthread_mutex_lock((void **)(&session_data.keystore_mutex)); #ifndef NDEBUG print_keystore(stderr, "before request"); #endif request_key(&datum->credentials.key); #ifndef NDEBUG print_keystore(stderr, "after request"); #endif gcry_pthread_mutex_unlock((void **)(&session_data.keystore_mutex)); /* Encrypted it using the default key */ salt_and_pepper((char *)(datum->credentials.key), NULL, &datum->buffet); encrypt_message(&datum->buffet, keystore.key); send_message(&datum->buffet, datum->sock); clear_buffet(&datum->buffet); /* Repeatedly poll for message streams */ while (handle_stream(datum) == BANKING_SUCCESS); /* Revoke the session key */ gcry_pthread_mutex_lock((void **)(&session_data.keystore_mutex)); #ifndef NDEBUG print_keystore(stderr, "before revoke"); #endif revoke_key(&datum->credentials.key); #ifndef NDEBUG print_keystore(stderr, "after revoke"); #endif gcry_pthread_mutex_unlock((void **)(&session_data.keystore_mutex)); } /* Cleanup (disconnect) */ #ifndef NDEBUG fprintf(stderr, "[thread %lu] INFO: worker disconnected from client\n", datum->id); #endif clear_buffet(&datum->buffet); destroy_socket(datum->sock); datum->sock = BANKING_FAILURE; } else { fprintf(stderr, "[thread %lu] ERROR: worker unable to connect\n", datum->id); } } /* Teardown */ handle_interruption(0); return NULL; }