From: Vibhav Pant vibhavp@gmail.com
--- dlls/winebth.sys/bthenum.c | 35 ++++++++++++ dlls/winebth.sys/dbus.c | 93 ++++++++++++++++++++++++++++++++ dlls/winebth.sys/unixlib.c | 10 ++++ dlls/winebth.sys/unixlib.h | 7 +++ dlls/winebth.sys/unixlib_priv.h | 2 + dlls/winebth.sys/winebluetooth.c | 15 ++++++ dlls/winebth.sys/winebluetooth.h | 10 ++++ dlls/winebth.sys/winebth.c | 20 +++++++ include/bthioctl.h | 18 +++++++ 9 files changed, 210 insertions(+)
diff --git a/dlls/winebth.sys/bthenum.c b/dlls/winebth.sys/bthenum.c index b12c8d9ab94..511dde8a189 100644 --- a/dlls/winebth.sys/bthenum.c +++ b/dlls/winebth.sys/bthenum.c @@ -1151,6 +1151,41 @@ static NTSTATUS WINAPI bthenum_ioctl( DEVICE_OBJECT *device, IRP *irp ) status = have_buf ? STATUS_SUCCESS : STATUS_INVALID_BUFFER_SIZE; break; } + case IOCTL_WINEBTH_SEND_AUTH_RESPONSE: + { + struct winebth_authentication_response *response = + (struct winebth_authentication_response *)irp->AssociatedIrp.SystemBuffer; + struct bthenum_phys_remote_radio_ext *remote_device; + BOOL found = FALSE; + if (response == NULL) + { + status = STATUS_INVALID_PARAMETER; + break; + } + if (insize < sizeof(*response)) + { + status = STATUS_INVALID_BUFFER_SIZE; + break; + } + if (response->auth_data.pin.length > 16) + { + status = STATUS_INVALID_PARAMETER; + break; + } + RtlEnterCriticalSection( &fdo->cs ); + LIST_FOR_EACH_ENTRY( remote_device, &fdo->devices, struct bthenum_phys_remote_radio_ext, entry ) + { + if (remote_device->props.address.ullLong == response->address && !remote_device->base.base.removed) + { + IoSkipCurrentIrpStackLocation( irp ); + found = TRUE; + status = IoCallDriver( fdo->parent_radio_pdo, irp ); + break; + } + } + RtlLeaveCriticalSection( &fdo->cs ); + if (!found) status = STATUS_DEVICE_DOES_NOT_EXIST; + } default: IoSkipCurrentIrpStackLocation( irp ); return IoCallDriver( fdo->parent_radio_pdo, irp ); diff --git a/dlls/winebth.sys/dbus.c b/dlls/winebth.sys/dbus.c index 31251806822..5f10b39fd08 100644 --- a/dlls/winebth.sys/dbus.c +++ b/dlls/winebth.sys/dbus.c @@ -2540,6 +2540,99 @@ BOOL bluez_auth_agent_unregister( void *connection, void *agent_ctx ) return success != 0; }
+NTSTATUS bluez_auth_agent_send_response( void *agent_ctx, + const struct winebluetooth_auth_response *response ) +{ + NTSTATUS ret; + DBusMessage *reply = NULL; + dbus_bool_t success = TRUE; + struct bluez_auth_agent_ctx *ctx = agent_ctx; + + pthread_mutex_lock( &ctx->lock ); + if (ctx->cur_request.status != BTH_AUTH_REQ_STATUS_WAITING_FOR_RESPONSE) + { + ret = STATUS_CANCELLED; + goto done; + } + reply = + response->negative_response + ? p_dbus_message_new_error( ctx->cur_request.message, "org.bluez.Error.Rejected", "" ) + : p_dbus_message_new_method_return( ctx->cur_request.message ); + if (!reply) + { + ret = STATUS_NO_MEMORY; + goto done; + } + if (response->negative_response) + { + p_dbus_connection_send_preallocated( ctx->cur_request.connection, ctx->cur_request.prealloc, + reply, NULL ); + bluez_auth_agent_ctx_reset( ctx, FALSE ); + ret = STATUS_SUCCESS; + goto done; + } + switch (response->auth_method) + { + case BLUETOOTH_AUTHENTICATION_METHOD_LEGACY: + if (ctx->cur_request.auth_method == BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY) + { + dbus_uint32_t passkey; + + errno = 0; + passkey = strtol( (char *)response->auth_data.pincode, NULL, 10 ); + if (errno) + { + /* The user has provided a non-numerical passkey, which wouldn't work. */ + p_dbus_message_unref( reply ); + reply = p_dbus_message_new_error( ctx->cur_request.message, + "org.bluez.Error.Rejected", "" ); + if (!reply) + { + ret = STATUS_CANCELLED; + goto done; + } + } + success = p_dbus_message_append_args( reply, DBUS_TYPE_UINT32, &passkey, + DBUS_TYPE_INVALID ); + } + else + { + const char *pin = (char *)response->auth_data.pincode; + success = + p_dbus_message_append_args( reply, DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID ); + } + break; + case BLUETOOTH_AUTHENTICATION_METHOD_PASSKEY: + if (ctx->cur_request.auth_method == BLUETOOTH_AUTHENTICATION_METHOD_LEGACY) + { + char pin[17]; + snprintf( pin, sizeof( pin ), "%d", (int)response->auth_data.passkey ); + success = p_dbus_message_append_args( reply, DBUS_TYPE_STRING, &pin, DBUS_TYPE_INVALID ); + } + else + { + dbus_uint32_t passkey = response->auth_data.passkey; + success = p_dbus_message_append_args( reply, DBUS_TYPE_UINT32, &passkey, DBUS_TYPE_INVALID ); + } + break; + default: + break; + } + if (!success) + { + ret = STATUS_NO_MEMORY; + goto done; + } + + p_dbus_connection_send_preallocated( ctx->cur_request.connection, ctx->cur_request.prealloc, + reply, NULL ); + bluez_auth_agent_ctx_reset( ctx, FALSE ); + ret = STATUS_SUCCESS; +done: + pthread_mutex_unlock( &ctx->lock ); + if (reply) p_dbus_message_unref( reply ); + return ret; +}
static BOOL bluez_auth_agent_have_auth_event( struct bluez_auth_agent_ctx *ctx, struct winebluetooth_auth_event *auth_event ) diff --git a/dlls/winebth.sys/unixlib.c b/dlls/winebth.sys/unixlib.c index 70162631747..f1263e27892 100644 --- a/dlls/winebth.sys/unixlib.c +++ b/dlls/winebth.sys/unixlib.c @@ -249,6 +249,15 @@ static NTSTATUS bluetooth_auth_agent_stop( void *args ) : STATUS_INTERNAL_ERROR; }
+static NTSTATUS bluetooth_auth_agent_send_response( void *args ) +{ + struct bluetooth_auth_agent_send_response_params *params = args; + + if (!dbus_connection) return STATUS_NOT_SUPPORTED; + + return bluez_auth_agent_send_response( (void *)params->agent, params->response ); +} + const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_init, bluetooth_shutdown, @@ -273,6 +282,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { bluetooth_auth_agent_init, bluetooth_auth_agent_start, bluetooth_auth_agent_stop, + bluetooth_auth_agent_send_response };
C_ASSERT( ARRAYSIZE( __wine_unix_call_funcs ) == unix_funcs_count ); diff --git a/dlls/winebth.sys/unixlib.h b/dlls/winebth.sys/unixlib.h index fa5b8e70066..5810d58e137 100644 --- a/dlls/winebth.sys/unixlib.h +++ b/dlls/winebth.sys/unixlib.h @@ -152,6 +152,12 @@ struct bluetooth_auth_agent_stop_params UINT_PTR auth_agent; };
+struct bluetooth_auth_agent_send_response_params +{ + UINT_PTR agent; + const struct winebluetooth_auth_response *response; +}; + enum bluetoothapis_funcs { unix_bluetooth_init, @@ -177,6 +183,7 @@ enum bluetoothapis_funcs unix_bluetooth_auth_agent_init, unix_bluetooth_auth_agent_start, unix_bluetooth_auth_agent_stop, + unix_bluetooth_auth_agent_send_response,
unix_funcs_count }; diff --git a/dlls/winebth.sys/unixlib_priv.h b/dlls/winebth.sys/unixlib_priv.h index 56042a959a9..bbf23b85d3a 100644 --- a/dlls/winebth.sys/unixlib_priv.h +++ b/dlls/winebth.sys/unixlib_priv.h @@ -60,5 +60,7 @@ extern NTSTATUS bluez_auth_agent_register( void *connection, void *ctx, BLUETOOTH_IO_CAPABILITY capabilities ); extern BOOL bluez_auth_agent_unregister( void *connection, void *agent_ctx ); extern UINT_PTR bluez_auth_agent_ctx_init( void ); +extern NTSTATUS bluez_auth_agent_send_response( void *agent_ctx, + const struct winebluetooth_auth_response *response ); #endif /* SONAME_LIBDBUS_1 */ #endif /* __WINE_BLUETOOTHAPIS_UNIXLIB_PRIV_H */ diff --git a/dlls/winebth.sys/winebluetooth.c b/dlls/winebth.sys/winebluetooth.c index 98f0afb9269..94da3762f3b 100644 --- a/dlls/winebth.sys/winebluetooth.c +++ b/dlls/winebth.sys/winebluetooth.c @@ -217,6 +217,21 @@ NTSTATUS winebluetooth_auth_agent_stop( winebluetooth_auth_agent_t agent ) return status; }
+NTSTATUS winebluetooth_send_auth_response( winebluetooth_auth_agent_t agent, + const struct winebluetooth_auth_response *response ) +{ + NTSTATUS status; + struct bluetooth_auth_agent_send_response_params params = {0}; + + TRACE("(%p, %p)\n", agent.handle, response ); + + params.agent = agent.handle; + params.response = response; + + status = UNIX_BLUETOOTH_CALL( bluetooth_auth_agent_send_response, ¶ms ); + return status; +} + NTSTATUS winebluetooth_init( void ) { NTSTATUS status; diff --git a/dlls/winebth.sys/winebluetooth.h b/dlls/winebth.sys/winebluetooth.h index 5efb3527ad0..f76061e05dc 100644 --- a/dlls/winebth.sys/winebluetooth.h +++ b/dlls/winebth.sys/winebluetooth.h @@ -291,6 +291,16 @@ union winebluetooth_auth_event_data } keypress; };
+struct winebluetooth_auth_response +{ + BLUETOOTH_AUTHENTICATION_METHOD auth_method; + union winebluetooth_auth_event_data auth_data; + BOOL negative_response; +}; + +NTSTATUS winebluetooth_send_auth_response( winebluetooth_auth_agent_t agent, + const struct winebluetooth_auth_response *response ); + enum winebluetooth_auth_event_type { BLUETOOTH_AUTH_EVENT_DEVICE_AUTH_REQUEST, diff --git a/dlls/winebth.sys/winebth.c b/dlls/winebth.sys/winebth.c index 59256369870..e67238e2208 100644 --- a/dlls/winebth.sys/winebth.c +++ b/dlls/winebth.sys/winebth.c @@ -243,6 +243,26 @@ static NTSTATUS WINAPI dispatch_bluetooth(DEVICE_OBJECT *device, IRP *irp ) ext->auth_agent_registered = !status ? FALSE : TRUE; break; } + case IOCTL_WINEBTH_SEND_AUTH_RESPONSE: + { + const struct winebth_authentication_response *response = + (struct winebth_authentication_response *)irp->AssociatedIrp.SystemBuffer; + struct winebluetooth_auth_response resp = {0}; + + resp.auth_method = response->auth_method; + resp.negative_response = response->auth_method; + if (response->auth_method == BLUETOOTH_AUTHENTICATION_METHOD_LEGACY) + { + memcpy( resp.auth_data.pincode, response->auth_data.pin.pin, + sizeof( response->auth_data.pin.pin ) ); + resp.auth_data.pincode[response->auth_data.pin.length] = '\0'; + } + else + resp.auth_data.passkey = response->auth_data.passkey; + + status = winebluetooth_send_auth_response( auth_agent, &resp ); + break; + }; default: break; } diff --git a/include/bthioctl.h b/include/bthioctl.h index f858f30c93e..5c0db3db413 100644 --- a/include/bthioctl.h +++ b/include/bthioctl.h @@ -48,6 +48,7 @@ #define IOCTL_WINEBTH_RADIO_STOP_DISCOVERY CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa7, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINEBTH_START_AUTH_AGENT CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa8, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_WINEBTH_STOP_AUTH_AGENT CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xa9, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_WINEBTH_SEND_AUTH_RESPONSE CTL_CODE(FILE_DEVICE_BLUETOOTH, 0xaa, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif
#define LOCAL_RADIO_DISCOVERABLE (0x0001) @@ -82,6 +83,23 @@ struct winebth_discovery_filter unsigned int bredr : 1; unsigned int le : 1; }; + +struct winebth_authentication_response +{ + BTH_ADDR address; + BLUETOOTH_AUTHENTICATION_METHOD auth_method; + union + { + ULONG passkey; + struct + { + UCHAR pin[16]; + USHORT length; + } pin; + } auth_data; + BOOL negative_response; +}; + #endif #endif /* __WINE_BTHIOCTL_H_ */