2015-07-10 15:11:49

by Gowtham Anandha Babu

[permalink] [raw]
Subject: [RFC 0/3] Expose AuthorizeGet opp

As similar to AuthorizePush, have created a method to authorize
incoming get request, so the user can select the file location at
runtime. Tested with PTS.

Gowtham Anandha Babu (3):
doc/obex-agent-api: Add AuthorizeGet method
test/obex: Add AuthorizeGet on Agent2 interface
obexd/opp: Add support for authorizing GET request

doc/obex-agent-api.txt | 30 ++++++++++++++++++++++++++++++
obexd/plugins/opp.c | 23 +++++++++++++++++++----
obexd/src/manager.c | 18 ++++++++++++------
obexd/src/manager.h | 2 +-
test/simple-obex-agent | 27 +++++++++++++++++++++++++++
5 files changed, 89 insertions(+), 11 deletions(-)

--
1.9.1



2015-07-15 11:43:42

by Luiz Augusto von Dentz

[permalink] [raw]
Subject: Re: [RFC 1/3] doc/obex-agent-api: Add AuthorizeGet method

Hi Gowtham,

On Fri, Jul 10, 2015 at 6:11 PM, Gowtham Anandha Babu
<[email protected]> wrote:
> This patch introduces the AuthorizeGet method to authorize
> incoming opp get request from opp clients.
> ---
> doc/obex-agent-api.txt | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/doc/obex-agent-api.txt b/doc/obex-agent-api.txt
> index 3923da6..ee27ba6 100644
> --- a/doc/obex-agent-api.txt
> +++ b/doc/obex-agent-api.txt
> @@ -59,3 +59,33 @@ Methods void Release()
> This method gets called to indicate that the agent
> request failed before a reply was returned. It cancels
> the previous request.
> +
> +Service unique name
> +Interface org.bluez.obex.Agent2
> +Object path freely definable
> +
> +Methods void Release()
> +
> + This method gets called when the service daemon
> + unregisters the agent. An agent can use it to do
> + cleanup tasks. There is no need to unregister the
> + agent, because when this method gets called it has
> + already been unregistered.
> +
> + string AuthorizeGet()

It should be fd Authorize(string name, string mimetype), the returned
fd is then used in the following way:

- GET: read(fd,...)
- PUT: write(fd,...)

> +
> + This method gets called when the service daemon
> + needs to accept/reject a Bluetooth object get request.
> + It request user the complete path of the local file.
> +
> + Returns the full path (including the filename) where
> + the local file exists.
> +
> + Possible errors: org.bluez.obex.Error.Rejected
> + org.bluez.obex.Error.Canceled
> +
> + void Cancel()
> +
> + This method gets called to indicate that the agent
> + request failed before a reply was returned. It cancels
> + the previous request.
> --
> 1.9.1

I think you misunderstood the general idea, the point of having a
different interface is that it give us the ability to change how the
agent works, most likely we want to make use of fd passing and make
Authorize generic for both PUT and GET commands, the way you did it we
would need 2 agents one for PUT and another for GET, also we need a
new Register method so the agent is able to detect obexd support the
new type of agent and register it.

We also discussed with gnome folks the possibility of the agent
registering its FTP shared folder instead of having it as command line
parameter, this could also be done using file descriptor using O_PATH
along with openat/fdopendir but I guess we can discuss about this
later, the important part is that new Register have a dict so this
kind of options can be added if necessary. Also it might be convenient
to add RequestDefaultAgent like it was done for the pairing agent so
that means we can have multiple agent, one for each user, but once the
session is changed it can request to become the default.

--
Luiz Augusto von Dentz

2015-07-10 15:11:50

by Gowtham Anandha Babu

[permalink] [raw]
Subject: [RFC 1/3] doc/obex-agent-api: Add AuthorizeGet method

This patch introduces the AuthorizeGet method to authorize
incoming opp get request from opp clients.
---
doc/obex-agent-api.txt | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)

diff --git a/doc/obex-agent-api.txt b/doc/obex-agent-api.txt
index 3923da6..ee27ba6 100644
--- a/doc/obex-agent-api.txt
+++ b/doc/obex-agent-api.txt
@@ -59,3 +59,33 @@ Methods void Release()
This method gets called to indicate that the agent
request failed before a reply was returned. It cancels
the previous request.
+
+Service unique name
+Interface org.bluez.obex.Agent2
+Object path freely definable
+
+Methods void Release()
+
+ This method gets called when the service daemon
+ unregisters the agent. An agent can use it to do
+ cleanup tasks. There is no need to unregister the
+ agent, because when this method gets called it has
+ already been unregistered.
+
+ string AuthorizeGet()
+
+ This method gets called when the service daemon
+ needs to accept/reject a Bluetooth object get request.
+ It request user the complete path of the local file.
+
+ Returns the full path (including the filename) where
+ the local file exists.
+
+ Possible errors: org.bluez.obex.Error.Rejected
+ org.bluez.obex.Error.Canceled
+
+ void Cancel()
+
+ This method gets called to indicate that the agent
+ request failed before a reply was returned. It cancels
+ the previous request.
--
1.9.1


2015-07-10 15:11:52

by Gowtham Anandha Babu

[permalink] [raw]
Subject: [RFC 3/3] obexd/opp: Add support for authorizing GET request

Add method call to authorize incoming GET request to
opp server.
---
obexd/plugins/opp.c | 23 +++++++++++++++++++----
obexd/src/manager.c | 18 ++++++++++++------
obexd/src/manager.h | 2 +-
3 files changed, 32 insertions(+), 11 deletions(-)

diff --git a/obexd/plugins/opp.c b/obexd/plugins/opp.c
index 5bb7667..5683776 100644
--- a/obexd/plugins/opp.c
+++ b/obexd/plugins/opp.c
@@ -77,7 +77,7 @@ static int opp_chkput(struct obex_session *os, void *user_data)
goto skip_auth;
}

- err = manager_request_authorization(user_data, &folder, &name);
+ err = manager_request_authorization(user_data, &folder, &name, "Push");
if (err < 0)
return -EPERM;

@@ -131,7 +131,7 @@ static int opp_put(struct obex_session *os, void *user_data)
static int opp_get(struct obex_session *os, void *user_data)
{
const char *type;
- char *folder, *path;
+ char *folder, *path, *name;
int err = 0;

if (obex_get_name(os))
@@ -142,8 +142,19 @@ static int opp_get(struct obex_session *os, void *user_data)
if (type == NULL)
return -EPERM;

- folder = g_strdup(obex_option_root_folder());
- path = g_build_filename(folder, "/vcard.vcf", NULL);
+ err = manager_request_authorization(user_data, &folder, &name, "Get");
+ if (err < 0)
+ return -EPERM;
+
+ if(folder == NULL)
+ folder = g_strdup(obex_option_root_folder());
+
+ if(name == NULL)
+ name = g_strdup("vcard.vcf");
+
+ path = g_build_filename(folder, name, NULL);
+
+ DBG("Filename: %s, Path: %s", name, path);

if (g_ascii_strcasecmp(type, VCARD_TYPE) == 0) {
if (obex_get_stream_start(os, path) < 0)
@@ -152,8 +163,12 @@ static int opp_get(struct obex_session *os, void *user_data)
} else
err = -EPERM;

+ manager_emit_transfer_started(user_data);
+
g_free(folder);
+ g_free(name);
g_free(path);
+
return err;
}

diff --git a/obexd/src/manager.c b/obexd/src/manager.c
index f84384a..be22ffd 100644
--- a/obexd/src/manager.c
+++ b/obexd/src/manager.c
@@ -51,6 +51,7 @@
#define TRANSFER_INTERFACE OBEXD_SERVICE ".Transfer1"
#define SESSION_INTERFACE OBEXD_SERVICE ".Session1"
#define AGENT_INTERFACE OBEXD_SERVICE ".Agent1"
+#define AGENT_INTERFACE_2 OBEXD_SERVICE ".Agent2"

#define TIMEOUT 60*1000 /* Timeout for user response (miliseconds) */

@@ -672,7 +673,7 @@ static gboolean auth_error(GIOChannel *io, GIOCondition cond, void *user_data)
}

int manager_request_authorization(struct obex_transfer *transfer,
- char **new_folder, char **new_name)
+ char **new_folder, char **new_name, char *request)
{
struct obex_session *os = transfer->session;
DBusMessage *msg;
@@ -689,12 +690,17 @@ int manager_request_authorization(struct obex_transfer *transfer,
if (!new_folder || !new_name)
return -EINVAL;

- msg = dbus_message_new_method_call(agent->bus_name, agent->path,
- AGENT_INTERFACE,
- "AuthorizePush");
-
- dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &transfer->path,
+ if (strcmp(request,"Push") == 0) {
+ msg = dbus_message_new_method_call(agent->bus_name, agent->path,
+ AGENT_INTERFACE,
+ "AuthorizePush");
+ dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &transfer->path,
DBUS_TYPE_INVALID);
+ }
+ else
+ msg = dbus_message_new_method_call(agent->bus_name, agent->path,
+ AGENT_INTERFACE_2,
+ "AuthorizeGet");

if (!g_dbus_send_message_with_reply(connection, msg, &call, TIMEOUT)) {
dbus_message_unref(msg);
diff --git a/obexd/src/manager.h b/obexd/src/manager.h
index d9781b2..5a265f1 100644
--- a/obexd/src/manager.h
+++ b/obexd/src/manager.h
@@ -37,6 +37,6 @@ void manager_emit_transfer_started(struct obex_transfer *transfer);
void manager_emit_transfer_progress(struct obex_transfer *transfer);
void manager_emit_transfer_completed(struct obex_transfer *transfer);
int manager_request_authorization(struct obex_transfer *transfer,
- char **new_folder, char **new_name);
+ char **new_folder, char **new_name, char *request);

DBusConnection *manager_dbus_get_connection(void);
--
1.9.1


2015-07-10 15:11:51

by Gowtham Anandha Babu

[permalink] [raw]
Subject: [RFC 2/3] test/obex: Add AuthorizeGet on Agent2 interface

Expose method for authroizing opp GET request.
---
test/simple-obex-agent | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)

diff --git a/test/simple-obex-agent b/test/simple-obex-agent
index 05ec4ed..41cd386 100755
--- a/test/simple-obex-agent
+++ b/test/simple-obex-agent
@@ -15,6 +15,7 @@ BUS_NAME = 'org.bluez.obex'
PATH = '/org/bluez/obex'
AGENT_MANAGER_INTERFACE = 'org.bluez.obex.AgentManager1'
AGENT_INTERFACE = 'org.bluez.obex.Agent1'
+AGENT_INTERFACE_2 = 'org.bluez.obex.Agent2'
TRANSFER_INTERFACE = 'org.bluez.obex.Transfer1'

def ask(prompt):
@@ -55,6 +56,32 @@ class Agent(dbus.service.Object):
print("Authorization Canceled")
self.pending_auth = False

+ @dbus.service.method(AGENT_INTERFACE_2, in_signature="",
+ out_signature="s")
+ def AuthorizeGet(self):
+ self.pending_auth = True
+ auth = ask("Authorize (Y/n):")
+
+ if auth == "n" or auth == "N":
+ self.pending_auth = False
+ raise dbus.DBusException(
+ "org.bluez.obex.Error.Rejected: "
+ "Not Authorized")
+
+ self.pending_auth = False
+ path = ask("Filename location:")
+
+ if path == "":
+ path = "vcard.vcf"
+
+ return path
+
+ @dbus.service.method(AGENT_INTERFACE_2, in_signature="",
+ out_signature="")
+ def Cancel(self):
+ print("Authorization Canceled")
+ self.pending_auth = False
+
if __name__ == '__main__':
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

--
1.9.1