static kim_error kim_error_set_message (kim_error in_error, kim_string in_message) { int lock_err = 0; kim_error err = KIM_NO_ERROR; kim_last_error last_error = NULL; err = lock_err = k5_mutex_lock (&kim_error_lock); if (!err) { last_error = k5_getspecific (K5_KEY_KIM_ERROR_MESSAGE); if (!last_error) { last_error = malloc (sizeof (*last_error)); if (!last_error) { err = KIM_OUT_OF_MEMORY_ERR; } else { last_error->code = KIM_NO_ERROR; err = k5_setspecific (K5_KEY_KIM_ERROR_MESSAGE, last_error); } } } if (!err) { strncpy (last_error->message, in_message, sizeof (last_error->message)); last_error->message[sizeof (last_error->message)-1] = '\0'; last_error->code = in_error; } if (!lock_err) { k5_mutex_unlock (&kim_error_lock); } return err; }
static char * get_thread_buffer () { char *cp; cp = k5_getspecific(K5_KEY_COM_ERR); if (cp == NULL) { cp = malloc(ET_EBUFSIZ); if (cp == NULL) { return NULL; } if (k5_setspecific(K5_KEY_COM_ERR, cp) != 0) { free(cp); return NULL; } } return cp; }
kim_string kim_error_message (kim_error in_error) { int lock_err = 0; kim_last_error last_error = NULL; kim_string message = NULL; lock_err = k5_mutex_lock (&kim_error_lock); if (!lock_err) { last_error = k5_getspecific (K5_KEY_KIM_ERROR_MESSAGE); if (last_error && last_error->code == in_error) { message = last_error->message; } } if (!lock_err) { k5_mutex_unlock (&kim_error_lock); } return message ? message : error_message (kim_error_remap (in_error)); }
kern_return_t k5_ipc_client_reply (mach_port_t in_reply_port, k5_ipc_inl_reply_t in_inl_reply, mach_msg_type_number_t in_inl_replyCnt, k5_ipc_ool_reply_t in_ool_reply, mach_msg_type_number_t in_ool_replyCnt) { kern_return_t err = KERN_SUCCESS; k5_ipc_connection_info cinfo = NULL; if (!err) { err = CALL_INIT_FUNCTION (k5_cli_ipc_thread_init); } if (!err) { cinfo = k5_getspecific (K5_KEY_IPC_CONNECTION_INFO); if (!cinfo || !cinfo->reply_stream) { err = EINVAL; } } if (!err) { if (in_inl_replyCnt) { err = k5_ipc_stream_write (cinfo->reply_stream, in_inl_reply, in_inl_replyCnt); } else if (in_ool_replyCnt) { err = k5_ipc_stream_write (cinfo->reply_stream, in_ool_reply, in_ool_replyCnt); } else { err = EINVAL; } } if (in_ool_replyCnt) { vm_deallocate (mach_task_self (), (vm_address_t) in_ool_reply, in_ool_replyCnt); } return err; }
static int save_error_string_nocopy(OM_uint32 minor_code, char *msg) { gsserrmap *p; int ret; #ifdef DEBUG fprintf(stderr, "%s(%lu, %s)", __func__, (unsigned long) minor_code, msg); #endif p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE); if (!p) { p = malloc(sizeof(*p)); if (p == NULL) { ret = 1; goto fail; } if (gsserrmap_init(p) != 0) { free(p); p = NULL; ret = 1; goto fail; } if (k5_setspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE, p) != 0) { gsserrmap_destroy(p); free(p); p = NULL; ret = 1; goto fail; } } ret = gsserrmap_replace_or_insert(p, minor_code, msg); fail: #ifdef DEBUG fprintf(stderr, " p=%p %s\n", (void *)p, ret ? "FAIL" : "SUCCESS"); #endif return ret; }
char *get_error_message(OM_uint32 minor_code) { gsserrmap *p = k5_getspecific(K5_KEY_GSS_KRB5_ERROR_MESSAGE); char *msg = NULL; #ifdef DEBUG fprintf(stderr, "%s(%lu, p=%p)", __func__, (unsigned long) minor_code, (void *) p); #endif if (p) { char **v = gsserrmap_find(p, minor_code); if (v) { msg = *v; #ifdef DEBUG fprintf(stderr, " FOUND!"); #endif } } if (msg == 0) msg = (char *)error_message((krb5_error_code)minor_code); #ifdef DEBUG fprintf(stderr, " -> %p/%s\n", (void *) msg, msg); #endif return msg; }
static boolean_t k5_ipc_reply_demux (mach_msg_header_t *request, mach_msg_header_t *reply) { boolean_t handled = 0; if (CALL_INIT_FUNCTION (k5_cli_ipc_thread_init) != 0) { return 0; } if (!handled && request->msgh_id == MACH_NOTIFY_NO_SENDERS) { k5_ipc_connection_info cinfo = k5_getspecific (K5_KEY_IPC_CONNECTION_INFO); if (cinfo) { cinfo->server_died = 1; } handled = 1; /* server died */ } if (!handled) { handled = k5_ipc_reply_server (request, reply); } return handled; }
int32_t k5_ipc_send_request (const char *in_service_id, int32_t in_launch_server, k5_ipc_stream in_request_stream, k5_ipc_stream *out_reply_stream) { int err = 0; int32_t done = 0; int32_t try_count = 0; mach_port_t server_port = MACH_PORT_NULL; k5_ipc_connection_info cinfo = NULL; k5_ipc_connection connection = NULL; mach_port_t reply_port = MACH_PORT_NULL; const char *inl_request = NULL; /* char * so we can pass the buffer in directly */ mach_msg_type_number_t inl_request_length = 0; k5_ipc_ool_request_t ool_request = NULL; mach_msg_type_number_t ool_request_length = 0; if (!in_request_stream) { err = EINVAL; } if (!out_reply_stream ) { err = EINVAL; } if (!err) { err = CALL_INIT_FUNCTION (k5_cli_ipc_thread_init); } if (!err) { /* depending on how big the message is, use the fast inline buffer or * the slow dynamically allocated buffer */ mach_msg_type_number_t request_length = k5_ipc_stream_size (in_request_stream); if (request_length > K5_IPC_MAX_INL_MSG_SIZE) { /*dprintf ("%s choosing out of line buffer (size is %d)", * __FUNCTION__, request_length); */ err = vm_read (mach_task_self (), (vm_address_t) k5_ipc_stream_data (in_request_stream), request_length, (vm_address_t *) &ool_request, &ool_request_length); } else { /*dprintf ("%s choosing in line buffer (size is %d)", * __FUNCTION__, request_length); */ inl_request_length = request_length; inl_request = k5_ipc_stream_data (in_request_stream); } } if (!err) { cinfo = k5_getspecific (K5_KEY_IPC_CONNECTION_INFO); if (!cinfo) { err = k5_ipc_client_cinfo_allocate (&cinfo); if (!err) { err = k5_setspecific (K5_KEY_IPC_CONNECTION_INFO, cinfo); } } if (!err) { int i, found = 0; for (i = 0; i < KIPC_SERVICE_COUNT; i++) { if (!strcmp (in_service_id, cinfo->connections[i].service_id)) { found = 1; connection = &cinfo->connections[i]; break; } } if (!found) { err = EINVAL; } } } if (!err) { err = k5_ipc_client_lookup_server (in_service_id, in_launch_server, TRUE, &server_port); } if (!err) { err = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &reply_port); } while (!err && !done) { if (!err && !MACH_PORT_VALID (connection->port)) { err = k5_ipc_client_create_client_connection (server_port, &connection->port); } if (!err) { err = k5_ipc_client_request (connection->port, reply_port, inl_request, inl_request_length, ool_request, ool_request_length); } if (err == MACH_SEND_INVALID_DEST) { if (try_count < 2) { try_count++; err = 0; } if (MACH_PORT_VALID (connection->port)) { mach_port_mod_refs (mach_task_self(), connection->port, MACH_PORT_RIGHT_SEND, -1 ); connection->port = MACH_PORT_NULL; } /* Look up server name again without using the cached copy */ err = k5_ipc_client_lookup_server (in_service_id, in_launch_server, FALSE, &server_port); } else { /* Talked to server, though we may have gotten an error */ done = 1; /* Because we use ",dealloc" ool_request will be freed by mach. * Don't double free it. */ ool_request = NULL; ool_request_length = 0; } } if (!err) { err = k5_ipc_stream_new (&cinfo->reply_stream); } if (!err) { mach_port_t old_notification_target = MACH_PORT_NULL; /* request no-senders notification so we know when server dies */ err = mach_port_request_notification (mach_task_self (), reply_port, MACH_NOTIFY_NO_SENDERS, 1, reply_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &old_notification_target); if (!err && old_notification_target != MACH_PORT_NULL) { mach_port_deallocate (mach_task_self (), old_notification_target); } } if (!err) { cinfo->server_died = 0; err = mach_msg_server_once (k5_ipc_reply_demux, K5_IPC_MAX_MSG_SIZE, reply_port, MACH_MSG_TIMEOUT_NONE); if (!err && cinfo->server_died) { err = ENOTCONN; } } if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) { err = 0; /* If server is not running just return an empty stream. */ } if (!err) { *out_reply_stream = cinfo->reply_stream; cinfo->reply_stream = NULL; } if (reply_port != MACH_PORT_NULL) { mach_port_destroy (mach_task_self (), reply_port); } if (ool_request_length) { vm_deallocate (mach_task_self (), (vm_address_t) ool_request, ool_request_length); } if (cinfo && cinfo->reply_stream) { k5_ipc_stream_release (cinfo->reply_stream); cinfo->reply_stream = NULL; } return err; }