RFC: obexapp - virtual root folder for each device

View: New views
20 Messages — Rating Filter:   Alert me  

RFC: obexapp - virtual root folder for each device

by Maksim Yevmenkin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

dear freebsd-bluetooth@ users,

please find attached patch to obexapp port that add new feature of
virtualizing root folder for each client device. this work was
inspired by and based work done by 'mi' < mi -plus- thun -at- aldan
-dot- algebra -dot- com>

background

various bluetooth obex profiles do not have notion of user
credentials. that could be very inconvenient when multiple client
devices want to store data on the same obex sever. the example that
was given to me by 'mi' is when two people (say, wife and husband)
want to back up their complete phone books onto the same server. the
problem is that most devices use some well known name, such as
phonebook.vcf and there is no obvious way to override it.

how does it work

obexapp now has new options '-R' that would turn new feature on.
first, default root folder is set as it was before (see man page '-r'
option). when client is connected, client's bd_addr is resolved to a
human readable name via bt_gethostbyaddr(3) call. if bd_addr is
resolved then obexapp will check for the subdirectory, under current
root, with the resolved name. if name was not resolved or resolution
has failed, then obexapp will look for a subdirectory that matches
client's bd_addr, i.e. '01:02:03:04:05:06'. if that fails, then
obexapp will look for "default" subdirectory. if later fails as well,
connection is terminated. if virtual root is found, obexapp will
chroot(2) into it.

possible setup

- create 'obex' user and 'obex' group
- create '/var/spool/obex' (or whatever you want for default root)
owned by 'obex' user/group
- user 'foo' creates ~/private directory under his home directory with
0700 permissions
- admin setups 'obex' directory under foo's ~/private/ directory with
0770 permissions, this directory is owned by 'obex' user. group is set
to foo's group
- admin setups symlink in /var/spool/obex/ called 'foo_cell' that
points to ~foo/private/obex
- admin adds entry in the /etc/bluetooth/hosts file to assign
'foo_cell' foo's cell phone bd_addr
- admin run obexapp server as 'obexapp -s -r /var/spool/obex -R -u obex -C 1'

every time foo's uses cell phone to send data to the obex server, the
data will end up in foo's ~/private/obex directory.

please give it a try and let me know it works.

thanks,
max

Index: main.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/main.c,v
retrieving revision 1.13
diff -u -r1.13 main.c
--- main.c 23 Apr 2007 18:29:18 -0000 1.13
+++ main.c 13 Apr 2009 21:25:08 -0000
@@ -65,7 +65,7 @@
 {
  struct sigaction sa;
  char *ep = NULL, *pri_name = NULL;
- int n, service, noninteractive;
+ int n, service, noninteractive, detach;
  context_t context;
  obex_ctrans_t custfunc;
 
@@ -83,7 +83,7 @@
  /* Prepare context */
  memset(&context, 0, sizeof(context));
  context.tfd = context.sfd = -1;
- context.detach = 1;
+ detach = 1;
 
  context.ls_size = OBEXAPP_BUFFER_SIZE;
  if ((context.ls = (char *) malloc(context.ls_size)) == NULL)
@@ -119,7 +119,7 @@
 
  /* Process command line options */
  service = noninteractive = 0;
- while ((n = getopt(argc, argv, "a:A:cC:dDfhl:m:nr:Ssu:")) != -1) {
+ while ((n = getopt(argc, argv, "a:A:cC:dDfhl:m:nr:RsSu:")) != -1) {
  switch (n) {
  case 'a':
  if (!bt_aton(optarg, &context.raddr)) {
@@ -180,7 +180,7 @@
  break;
 
  case 'd': /* do not detach server */
- context.detach = 0;
+ detach = 0;
  break;
 
  case 'D': /* use stdin/stdout */
@@ -217,6 +217,11 @@
  err(1, "Could not realpath(%s)", optarg);
  break;
 
+ case 'R': /* virtualize root for each device */
+ context.vroot = 1;
+ context.secure = 1;
+ break;
+
  case 's': /* server */
  if (noninteractive)
  usage(basename(argv[0]));
@@ -269,23 +274,10 @@
  log_open("obexapp", pri_name, 0);
 
  /* Detach server (if required) */
- if (context.server && context.detach) {
- pid_t pid = fork();
-
- if (pid == (pid_t) -1) {
- log_err("%s(): Could not fork. %s (%d)",
- __func__, strerror(errno), errno);
- exit(1);
- }
-
- if (pid != 0)
- exit(0);
-
- if (daemon(0, 0) < 0) {
- log_err("%s(): Could not daemon. %s (%d)",
- __func__, strerror(errno), errno);
- exit(1);
- }
+ if (context.server && detach && daemon(0, 0) < 0) {
+ log_err("%s(): Could not daemon. %s (%d)",
+ __func__, strerror(errno), errno);
+ exit(1);
  }
 
  /* Initialize OBEX */
Index: obexapp.1
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/obexapp.1,v
retrieving revision 1.15
diff -u -r1.15 obexapp.1
--- obexapp.1 21 May 2007 15:55:35 -0000 1.15
+++ obexapp.1 13 Apr 2009 23:15:03 -0000
@@ -54,7 +54,7 @@
 .Ar parameters
 .Nm
 .Fl s
-.Op Fl dDSh
+.Op Fl dDSRh
 .Op Fl A Ar BD_ADDR
 .Fl C Ar channel
 .Op Fl m Ar MTU
@@ -193,6 +193,12 @@
 Defaults to the maximum supported value.
 .It Fl n
 Work in the non-interactive client mode.
+.It Fl R
+Virtualize root folder for each client device in server mode.
+Will automatically turn on secure mode, i.e.
+.Fl S
+option.
+Please read section below for a complete description.
 .It Fl r Ar path
 Specify root folder.
 Default root folder in the server mode is
@@ -216,6 +222,43 @@
 The value specified may be either a username or a numeric user id.
 This only works if server was started as root.
 .El
+.Sh VIRTUAL ROOT FOLDERS
+When accepting connections in server mode,
+.Nm
+will attempt to find a subdirectory that would act as a virtual root
+folder for the connecting device.
+Virtual root folders must reside under default root folder which is set
+with
+.Fl r
+option.
+The rules are as follows:
+.Bl -enum -offset indent -compact
+.It
+.Nm
+will try to resolve connecting device's BD_ADDR using
+.Xr bt_gethostbyaddr 3
+call and check for a subdirectory that matches resolved name (if any);
+.It
+.Nm
+will check for a subdirectory that matches connecting device's BD_ADDR;
+.It
+.Nm
+will check for a subdirectory, named
+.Dq default ;
+.El
+If none of the above matches, then the connection to the client is terminated.
+Otherwise,
+.Nm
+will change default root folder the the found subdirectory.
+This allows the same system to intelligently distinguish different
+client devices as belonging to different users.
+An administrator can set up the subdirectories for
+known devices under
+.Pa /var/spool/obex
+(or wherever, see
+.Fl r
+option) for each user, or even as symlinks to each user's home directory
+(or a subdirectory thereof).
 .Sh LOCALE SUPPORT
 The
 .Nm
@@ -325,6 +368,13 @@
 .Dv ANY
 address and RFCOMM channel
 .Li 1 .
+.It ln -s Ar /home/wallaby Ar /var/spool/obex/00:01:02:03:04:05
+.It chown -h wallaby Ar /var/spool/obex/00:01:02:03:04:05
+Whenever the device with BD_ADDR of 00:01:02:03:04:05 connects,
+.Nm
+running in server mode will switch to user ID
+.Ar wallaby
+and use their home directory as the top-level for the connection.
 .El
 .Ss Level 1 Information Access
 The first level involves the basic ability to put an object (such as a vCard)
Index: obexapp.h
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/obexapp.h,v
retrieving revision 1.9
diff -u -r1.9 obexapp.h
--- obexapp.h 23 Apr 2007 18:29:18 -0000 1.9
+++ obexapp.h 13 Apr 2009 21:22:29 -0000
@@ -87,8 +87,8 @@
  unsigned server     : 1; /* server mode? */
  unsigned secure     : 1; /* secure mode? */
  unsigned done       : 1; /* done? */
- unsigned detach     : 1; /* detach server? */
  unsigned fbs        : 1; /* Folder Browsing Service */
+ unsigned vroot    : 1; /* virtualize device's root */
  unsigned reserved   : 2;
 
  /* local SDP session (server only) */
Index: server.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/server.c,v
retrieving revision 1.11
diff -u -r1.11 server.c
--- server.c 9 Apr 2009 23:16:31 -0000 1.11
+++ server.c 13 Apr 2009 23:10:31 -0000
@@ -1,6 +1,8 @@
 /*
  * server.c
- *
+ */
+
+/*-
  * Copyright (c) 2002 Maksim Yevmenkin <m_evmenkin@...>
  * All rights reserved.
  *
@@ -89,6 +91,11 @@
 static char const * const ls_parent_folder =
  "<parent-folder/>\n";
 
+static int obexapp_server_set_root
+ (context_p context);
+static int obexapp_server_set_device_root
+ (context_p context);
+
 /* OBEX request handlers */
 static obexapp_request_handler_t obexapp_server_request_connect;
 static obexapp_request_handler_t obexapp_server_request_disconnect;
@@ -114,7 +121,6 @@
 obexapp_server(obex_t *handle)
 {
  context_p context = (context_p) OBEX_GetUserData(handle);
- struct passwd *pw = NULL;
  int error = -1;
  struct sockaddr_rfcomm addr;
 
@@ -131,26 +137,6 @@
  goto done;
  }
 
- if (context->user != NULL) {
- if (atoi(context->user) != 0)
- pw = getpwuid(atoi(context->user));
- else
- pw = getpwnam(context->user);
-
- if (pw == NULL) {
- log_err("%s(): Unknown user %s", __func__,
- context->user);
- goto done;
- }
- }
-
- if (context->root[0] == '\0') {
- if (pw == NULL)
- strlcpy(context->root, OBEXAPP_ROOT_DIR, PATH_MAX);
- else
- strlcpy(context->root, pw->pw_dir, PATH_MAX);
- }
-
  log_info("%s: Starting OBEX server", __func__);
 
  if (OBEX_SetTransportMTU(handle, context->mtu, context->mtu) < 0) {
@@ -162,7 +148,7 @@
  addr.rfcomm_len = sizeof(addr);
  addr.rfcomm_family = AF_BLUETOOTH;
  addr.rfcomm_channel = context->channel;
- memcpy(&addr.rfcomm_bdaddr, &context->raddr, sizeof(context->raddr));
+ memcpy(&addr.rfcomm_bdaddr, &context->laddr, sizeof(context->laddr));
 
  if (OBEX_ServerRegister(handle, (struct sockaddr *) &addr,
  sizeof(addr)) < 0) {
@@ -170,40 +156,8 @@
  goto done;
  }
 
- if (getuid() == 0) {
- if (context->secure) {
- if (chroot(context->root) < 0) {
- log_err("%s(): Could not chroot(%s). %s (%d)",
- __func__, context->root,
- strerror(errno), errno);
- goto done;
- }
-
- strlcpy(context->root, "/", PATH_MAX);
- }
-
- if (pw != NULL) {
- if (setgid(pw->pw_gid) < 0) {
- log_err("%s(): Could not setgid(%d). %s (%d)",
- __func__, pw->pw_gid, strerror(errno),
- errno);
- goto done;
- }
-
- if (setuid(pw->pw_uid) < 0) {
- log_err("%s(): Could not setuid(%d). %s (%d)",
- __func__, pw->pw_uid, strerror(errno),
- errno);
- goto done;
- }
- }
- }
-
- if (chdir(context->root) < 0) {
- log_err("%s(): Could not chdir(%s). %s (%d)",
- __func__, context->root, strerror(errno), errno);
+ if (obexapp_server_set_root(context) < 0)
  goto done;
- }
 
  log_debug("%s(): Entering event processing loop...", __func__);
 
@@ -227,6 +181,155 @@
 } /* obexapp_server */
 
 /*
+ * Set server root
+ */
+
+int
+obexapp_server_set_root(context_p context)
+{
+ struct passwd *pw;
+ char *ep;
+ uid_t uid;
+
+ if (context->user != NULL) {
+ uid = strtoul(context->user, &ep, 10);
+ if (*ep != '\0')
+ pw = getpwnam(context->user);
+ else
+ pw = getpwuid(uid);
+
+ if (pw == NULL) {
+ log_err("%s(): Unknown user %s",
+ __func__, context->user);
+ return (-1);
+ }
+
+ log_debug("%s(): Requested to run as '%s' uid=%d, gid=%d",
+ __func__, context->user, pw->pw_uid, pw->pw_gid);
+ } else
+ pw = NULL;
+
+ /* Set default root */
+ if (context->root[0] == '\0') {
+ if (pw == NULL)
+ strlcpy(context->root, OBEXAPP_ROOT_DIR, PATH_MAX);
+ else
+ strlcpy(context->root, pw->pw_dir, PATH_MAX);
+ }
+
+ if (chdir(context->root) < 0) {
+ log_err("%s(): Could not chdir(%s). %s (%d)",
+ __func__, context->root, strerror(errno), errno);
+ return (-1);
+ }
+
+ /* Set device specific root */
+ if (context->vroot && obexapp_server_set_device_root(context) <= 0)
+ return (-1);
+
+ log_debug("%s(): Using root %s", __func__, context->root);
+
+ if (context->secure) {
+ if (chroot(context->root) < 0) {
+ log_err("%s(): Could not chroot(%s). %s (%d)",
+ __func__, context->root,
+ strerror(errno), errno);
+ return (-1);
+ }
+
+ strlcpy(context->root, "/", PATH_MAX);
+
+ log_debug("%s(): Secure mode enabled", __func__);
+ }
+
+ if (pw != NULL) {
+ if (setgid(pw->pw_gid) < 0) {
+ log_err("%s(): Could not setgid(%d). %s (%d)",
+ __func__, pw->pw_gid, strerror(errno), errno);
+ return (-1);
+ }
+
+ if (setuid(pw->pw_uid) < 0) {
+ log_err("%s(): Could not setuid(%d). %s (%d)",
+ __func__, pw->pw_uid, strerror(errno), errno);
+ return (-1);
+ }
+
+ log_debug("%s(): Running as uid=%d, gid=%d",
+ __func__, getuid(), getgid());
+ }
+
+ return (0);
+} /* obexapp_server_set_root */
+
+/*
+ * Set device specific server root
+ */
+
+static int
+obexapp_server_set_device_root(context_p context)
+{
+ char const *root[] = { NULL, NULL, NULL };
+ struct hostent *he;
+ struct stat sb;
+ int n;
+
+ n = 0;
+
+ he = bt_gethostbyaddr((char const *) &context->raddr,
+ sizeof(bdaddr_t), AF_BLUETOOTH);
+ if (he != NULL)
+ root[n ++] = (char const *) he->h_name;
+
+ root[n ++] = bt_ntoa(&context->raddr, NULL);
+
+ root[n ++] = "default";
+
+ for (n = 0; n < 3; n ++) {
+ if (root[n] == NULL)
+ break;
+
+ log_debug("%s(): Checking for %s/%s subdirectory",
+ __func__, context->root, root[n]);
+
+ if (stat(root[n], &sb) < 0) {
+ if (errno == ENOENT)
+ continue;
+
+ log_err("%s(): Could not lstat(%s/%s). %s (%d)",
+ __func__, context->root, root[n],
+ strerror(errno), errno);
+
+ return (-1);
+ }
+
+ if (!S_ISDIR(sb.st_mode)) {
+ log_debug("%s(): Ignoring %s/%s. Not a directory",
+ __func__, context->root, root[n]);
+ continue;
+ }
+
+ strlcat(context->root, "/", PATH_MAX);
+ strlcat(context->root, root[n], PATH_MAX);
+
+ if (chdir(root[n]) < 0) {
+ log_err("%s(): Could not chdir(%s). %s (%d)",
+ __func__, context->root, strerror(errno),
+ errno);
+ return (-1);
+ }
+
+ return (1);
+ }
+
+ log_notice("%s(): Could not set device specific root for the device " \
+ "bdaddr %s (%s)", __func__, root[1],
+ root[0]? root[0] : "-no-name-");
+
+ return (0);
+} /* obexapp_server_set_device_root */
+
+/*
  * Process OBEX_EV_REQHINT event
  */
 
@@ -565,6 +668,15 @@
  }
  }
 
+ if (chmod(context->temp, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) < 0) {
+ log_err("%s(): Could not chmod(%s). %s (%d)",
+ __func__, context->temp,
+ strerror(errno), errno);
+
+ codes = obexapp_util_errno2response(errno);
+ goto done;
+ }
+
  if (rename(context->temp, context->file) < 0) {
  log_err("%s(): Could not rename(%s, %s). %s (%d)",
  __func__, context->temp,
Index: transport.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/transport.c,v
retrieving revision 1.13
diff -u -r1.13 transport.c
--- transport.c 21 May 2007 15:55:35 -0000 1.13
+++ transport.c 10 Apr 2009 18:26:08 -0000
@@ -280,6 +280,9 @@
  return (-1);
  }
 
+ memcpy(&context->raddr, &addr.rfcomm_bdaddr,
+ sizeof(context->raddr));
+
  return (1);
  }
 
Index: util.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/util.c,v
retrieving revision 1.14
diff -u -r1.14 util.c
--- util.c 10 Apr 2009 17:26:03 -0000 1.14
+++ util.c 10 Apr 2009 18:05:23 -0000
@@ -425,9 +425,7 @@
  * string, so always pass a copy.
  */
 
- strncpy(n, name, sizeof(n));
- n[sizeof(n) - 1] = '\0';
-
+ strlcpy(n, name, sizeof(n));
  snprintf(temp, temp_size, "%s/XXXXXXXX", dirname(n));
 
  return (mkstemp(temp));

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Maksim Yevmenkin написав(ла):

> possible setup
>
> - create 'obex' user and 'obex' group
> - create '/var/spool/obex' (or whatever you want for default root)
> owned by 'obex' user/group
> - user 'foo' creates ~/private directory under his home directory with
> 0700 permissions
> - admin setups 'obex' directory under foo's ~/private/ directory with
> 0770 permissions, this directory is owned by 'obex' user. group is set
> to foo's group
> - admin setups symlink in /var/spool/obex/ called 'foo_cell' that
> points to ~foo/private/obex
> - admin adds entry in the /etc/bluetooth/hosts file to assign
> 'foo_cell' foo's cell phone bd_addr
> - admin run obexapp server as 'obexapp -s -r /var/spool/obex -R -u obex -C 1'
>
> every time foo's uses cell phone to send data to the obex server, the
> data will end up in foo's ~/private/obex directory.
>
> please give it a try and let me know it works.
>  
I think, Maksim's proposal is suboptimal, because the uploaded files end
up owned by the new user obex, rather than the actual user (foo in the
above example), which will make file-manipulations on the system itself
more difficult (obex-owned will they not have 600 permissions?). It also
necessitates creation of a new UID without the security benefit of
having the daemon run under that UID permanently (but only switching
after accepting each connection)...

My proposal -- discussed with Maksim at length -- would *derive the
user-ID from the ownership of the link*. The sample set up would then be
as follows. Suppose, user named wallaby has a device with BD_ADDR
01:02:03:04:05:06. The user would create a subdirectory for their
bluetooth files (or use something existing, like ~/Desktop/):

    wallaby@tasmania (11) mkdir ~/bluetooth

root will then -- on wallaby's request -- tell obexapp about it:

    root@tasmania (111) ln -s ~wallaby/bluetooth
    /var/spool/obex/01:02:03:04:05:06
    root@tasmania (112) chown -h wallaby ~wallaby/bluetooth
    /var/spool/obex/01:02:03:04:05:06

The second of the above root's lines is what will -- under my proposal
-- tell obexapp-daemon, who shall own any files uploaded by the device.
If started as root, instead of becoming 'obex', obexapp will become
'wallaby'...

Upon accepting a connection, the server will do the same lookups as
Maksim's version is doing, cd/chroot into the subdirectory, and setuid
to the proper UID (such as wallaby's in this example).

The attached patch can be dropped into /usr/ports/comms/obexapp/files/ .
The only functionality still missing from it compared to Maksim's is the
bt_gethostbyaddr(3) lookup -- only the numeric BD_ADDR is currently
considered. This is not a significant difference between proposals,
though...

My proposal has other, not so significant differences -- it allows the
BD_ADDR-entries in /var/spool/obex to be non-directories (files, broken
links a'la /etc/make.conf, even sockets). Even if a chdir into such an
entry fails, the ID of the entry's owner will still be used to
determine, which user shall own any uploaded files, etc. even though all
such files will end up in the same directory (as they do with the
current version of obexapp).

Maksim thought, offering such flexibility would be too confusing...

I agree, that chroot-ing (rather than merely chdir-ing) into such a
"virtual root" directory makes sense. The only material difference
between our proposals is my deriving the desired UID from the ownership
of the found BD_ADDR entry vs. Maksim's always using the user specified
on command-line (such as 'obex').

Yours,

    -mi


--- obexapp.1 2007-05-21 11:55:35.000000000 -0400
+++ obexapp.1 2009-04-09 22:15:22.000000000 -0400
@@ -217,4 +217,30 @@
 This only works if server was started as root.
 .El
+.Sh Per-user configurations
+When accepting connections in server mode,
+.Nm
+will check, if there is an entry named after the connecting device's
+BD_ADDR in the root-path (default or specified by the
+.Fl r
+option). If found, the entry will be used as follows:
+.Bl -enum -offset indent -compact
+.It
+The group ID will be changed to that, which owns the entry.
+.It
+If
+.Nm
+is running as root, it will change to the user, that owns the entry.
+.It
+If the entry is itself a directory and chdir into it succeeds, it will
+be used as the top-level.
+.El
+This allows the same system to intelligently distinguish different Bluetooth devices
+as belonging to different users. An administrator can set up the subdirectories for
+known devices under
+.Pa /var/spool/obex
+(or wherever, see
+.Fl r
+option) for each user, or even as symlinks to each user's home directory
+(or a subdirectory thereof).
 .Sh LOCALE SUPPORT
 The
@@ -326,4 +352,11 @@
 address and RFCOMM channel
 .Li 1 .
+.It ln -s Ar /home/wallaby Ar /var/spool/obex/00:01:02:03:04:05
+.It chown -h wallaby Ar /var/spool/obex/00:01:02:03:04:05
+Whenever the device with BD_ADDR of 00:01:02:03:04:05 connects,
+.Nm
+running in server mode will switch to user ID
+.Ar wallaby
+and use their home directory as the top-level for the connection.
 .El
 .Ss Level 1 Information Access
--- transport.c 2007-05-21 11:55:35.000000000 -0400
+++ transport.c 2009-04-09 20:53:27.000000000 -0400
@@ -271,4 +272,7 @@
  addr.rfcomm_channel, getpid());
 
+ memcpy(&context->raddr, &addr.rfcomm_bdaddr,
+                                        sizeof(context->raddr));
+
  if (daemon(1, 0) < 0) {
  log_err("%s(): Could not daemon. %s (%d)",
--- work/obexapp/server.c 2009-04-10 12:29:53.000000000 -0400
+++ work/obexapp/server.c 2009-04-13 20:33:16.000000000 -0400
@@ -110,5 +110,4 @@
  * OBEX server
  */
-
 int
 obexapp_server(obex_t *handle)
@@ -118,4 +117,8 @@
  int error = -1;
  struct sockaddr_rfcomm addr;
+ struct stat sb;
+ const char *subdir = bt_ntoa(&context->raddr, NULL);
+ uid_t uid = 0;
+ gid_t gid = getgid();
 
  context->ss = sdp_open_local(NULL);
@@ -143,4 +146,6 @@
  goto done;
  }
+ uid = pw->pw_uid;
+ gid = pw->pw_gid;
  }
 
@@ -171,4 +176,36 @@
  }
 
+ if (chdir(context->root) < 0) {
+ log_err("%s(): Could not chdir(%s). %s (%d)",
+ __func__, context->root, strerror(errno), errno);
+ goto done;
+ }
+
+ log_debug("%s(): checking for %s/%s subdirectory", __func__,
+    context->root, subdir);
+ if (lstat(subdir, &sb) == 0) {
+ log_debug("%s(): %s/%s exists and belongs to uid %d",
+    __func__, context->root, subdir, sb.st_uid);
+ uid = sb.st_uid;
+ gid = sb.st_gid;
+ if (chdir(subdir))
+ log_debug("%s(): chdir to %s failed: %s. Will remain "
+    "on top (uid %ld).", __func__, subdir, strerror(errno),
+    (long)uid);
+ else
+ getwd(context->root);
+
+ log_debug("%s(): using %s", __func__, context->root);
+ } else switch (errno) {
+ case ENOENT:
+ log_debug("%s(): %s/%s not found", __func__,
+    context->root, subdir);
+ break;
+ default:
+ log_err("%s(): %s/%s: %s", __func__, context->root, subdir,
+    strerror(errno));
+ goto done;
+ }
+
  if (getuid() == 0) {
  if (context->secure) {
@@ -183,25 +220,19 @@
  }
 
- if (pw != NULL) {
- if (setgid(pw->pw_gid) < 0) {
- log_err("%s(): Could not setgid(%d). %s (%d)",
- __func__, pw->pw_gid, strerror(errno),
- errno);
- goto done;
- }
-
- if (setuid(pw->pw_uid) < 0) {
+ if (uid) {
+ if (setuid(uid) < 0) {
  log_err("%s(): Could not setuid(%d). %s (%d)",
- __func__, pw->pw_uid, strerror(errno),
+ __func__, uid, strerror(errno),
  errno);
  goto done;
  }
  }
- }
 
- if (chdir(context->root) < 0) {
- log_err("%s(): Could not chdir(%s). %s (%d)",
- __func__, context->root, strerror(errno), errno);
- goto done;
+ if (gid != getgid() && setgid(gid) < 0) {
+ log_err("%s(): Could not setgid(%d). %s (%d)",
+ __func__, gid, strerror(errno),
+ errno);
+ goto done;
+ }
  }
 

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Maksim Yevmenkin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/4/13 Mikhail T. <mi+thun@...>:

> Maksim Yevmenkin написав(ла):
>> possible setup
>>
>> - create 'obex' user and 'obex' group
>> - create '/var/spool/obex' (or whatever you want for default root)
>> owned by 'obex' user/group
>> - user 'foo' creates ~/private directory under his home directory with
>> 0700 permissions
>> - admin setups 'obex' directory under foo's ~/private/ directory with
>> 0770 permissions, this directory is owned by 'obex' user. group is set
>> to foo's group
>> - admin setups symlink in /var/spool/obex/ called 'foo_cell' that
>> points to ~foo/private/obex
>> - admin adds entry in the /etc/bluetooth/hosts file to assign
>> 'foo_cell' foo's cell phone bd_addr
>> - admin run obexapp server as 'obexapp -s -r /var/spool/obex -R -u obex -C 1'
>>
>> every time foo's uses cell phone to send data to the obex server, the
>> data will end up in foo's ~/private/obex directory.
>>
>> please give it a try and let me know it works.
>>
> I think, Maksim's proposal is suboptimal, because the uploaded files end
> up owned by the new user obex, rather than the actual user (foo in the
> above example), which will make file-manipulations on the system itself
> more difficult (obex-owned will they not have 600 permissions?). It also

permissions on files will be set to 0660.

> necessitates creation of a new UID without the security benefit of
> having the daemon run under that UID permanently (but only switching
> after accepting each connection)...

i beg to differ. main process (the one that accepts connection) is
running with elevated privileges, yes. however, the process that
handles the actual connection from the client is running with reduced
privileges. so, there is a security benefit. also, obexapp will chroot
into virtual root.

> My proposal -- discussed with Maksim at length -- would *derive the
> user-ID from the ownership of the link*. The sample set up would then be
> as follows. Suppose, user named wallaby has a device with BD_ADDR
> 01:02:03:04:05:06. The user would create a subdirectory for their
> bluetooth files (or use something existing, like ~/Desktop/):

as i tried to explain, there are few problems (imo) with your patch.
one example: what happens when remote client decides to create a
directory which matches another client's bd_addr or name? i also do
not like the fact that client are allowed to "escape" from their
virtual root directory. another thing is that you pretty much force
new behavior and not giving any control to disable it. what is worse,
new behavior is controlled by file system elements which remote
clients can potentially see, create and/or modify.

[...]

> My proposal has other, not so significant differences -- it allows the
> BD_ADDR-entries in /var/spool/obex to be non-directories (files, broken
> links a'la /etc/make.conf, even sockets). Even if a chdir into such an
> entry fails, the ID of the entry's owner will still be used to
> determine, which user shall own any uploaded files, etc. even though all
> such files will end up in the same directory (as they do with the
> current version of obexapp).
>
> Maksim thought, offering such flexibility would be too confusing...

please explain what does it buy you exactly? so, great, you can
control file ownership in the _same_ directory. like i said, unless
you set sticky bit on the directory (which is evil, imo) and make it
0777 there is still a problem with sharing files (either obexapp
running under new id won't be able to write to the root directory or
everybody will be able to delete each others files). either way, its
not that different from what obexapp does right now.

> I agree, that chroot-ing (rather than merely chdir-ing) into such a
> "virtual root" directory makes sense. The only material difference
> between our proposals is my deriving the desired UID from the ownership
> of the found BD_ADDR entry vs. Maksim's always using the user specified
> on command-line (such as 'obex').

i'm actually not feeling very strongly about this. my initial choice
is to be on a safe side. basically, what i'm trying to guard against
is when someone put a symlink owned by root into the obexapp root
folder. this is very easy thing to do, imo. i personally did it :)
basically this type of misconfiguration will make obexapp continue to
run with elevated privileges while servicing clients requests and that
is a 'bad thing (tm)' :)

i also must say that we are trying to solve the problem at the wrong
level. more specifically, for phone book back up you probably want to
use something else (like sync-ml for example) not not obexapp.
bluetooth obex profiles are just completely oblivious to the fact that
clients might need to supply credentials. its all strictly personal.
so what i did, it basically provided mechanism to extend it in a
similar manner.

thanks,
max
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Maksim Yevmenkin написав(ла):
>> I think, Maksim's proposal is suboptimal, because the uploaded files end
>> up owned by the new user obex, rather than the actual user (foo in the
>> above example), which will make file-manipulations on the system itself
>> more difficult (obex-owned will they not have 600 permissions?). It also
>>    
> permissions on files will be set to 0660.
>  
I didn't see, where you do this -- simply using mkstemp will result in
600. But it can be done, of course. However, it is still imperfect,
because all of the bluetooth users would have to be listed in obex'
group and so there can be no more than 20 of them (I think, that's the
limit on a group size).

In any case, being owned by the actual user seems far more
straightforward...
>> necessitates creation of a new UID without the security benefit of
>> having the daemon run under that UID permanently (but only switching
>> after accepting each connection)...
>>    
> i beg to differ. main process (the one that accepts connection) is
> running with elevated privileges, yes.
>From the security standpoint, this negates all/most benefits of having a
dedicated UID for the service. The security people will tell you, that,
as long as the root-owned process is always running and listening to
connections, it can some day be fooled and so they don't like it anyway.
> however, the process that
> handles the actual connection from the client is running with reduced
> privileges. so, there is a security benefit.
It will drop the root-privileges under my proposal as well. It is just
that the new UID will be that of the connecting user as determined by
the BD_ADDR match, if such a match can be found. Otherwise, yes, it
should become whatever user is specified with the -u switch.
> also, obexapp will chroot
> into virtual root.
>  
Yes, I agree, this is advantageous.

> i'm actually not feeling very strongly about this. my initial choice
> is to be on a safe side. basically, what i'm trying to guard against
> is when someone put a symlink owned by root into the obexapp root
> folder. this is very easy thing to do, imo. i personally did it :)
>  
The only thing I do feel strongly about, is that, when a matching
directory entry is found, the server shall perform a setuid not to the
generic 'obex' user, but to the owner of that entry (and chroot into it,
yes).

I do not think, you should give special meaning to entry named "default"
-- because that would require special handling of the case, when
somebody's BD_ADDR resolves to name "default". I'd say, it is Ok, if no
match for the device is found, to remain in the top-level directory
(after dropping the root-privileges). But, again, no strong feeling
about this.

My other ideas (such as the matching entries not necessarily being
subdirectories) came from trying to maintain compatibility with the
current operations (where everything lives in the same directory), while
still allowing the created files to belong to different, cooperating users.

> basically this type of misconfiguration will make obexapp continue to
> run with elevated privileges while servicing clients requests and that
> is a 'bad thing (tm)' :)
>  
I agree, that continuing to run as root after accepting connection is
bad -- if a matching entry is not found, the server, indeed, ought to
setuid to some non-root user (as set by the -u switch or determined from
the ownership of the top-level itself). However, the above-mentioned
cooperation may still have its uses for some people. That said, they can
have all their BD_ADDR symlinks point to the same directory and
cooperate there, so I don't feel strongly about it either.
> i also must say that we are trying to solve the problem at the wrong
> level. more specifically, for phone book back up you probably want to
> use something else (like sync-ml for example) not not obexapp.
>  
Not sure, what "sync-ml" is (there is no such port). But what about
dropping camera's pictures and videos? People would certainly expect to
be able to do that straight from their devices (rather than by running a
client of some sort), and find the files somewhere under their home
directories (perhaps in ~/Desktop).

So, I agree with most of your change, except the UID part -- in case a
subdirectory-entry with a matching name is found, the argument of the
setuid() (and setgid()) call should be the UID (and GID) of the entry
(as determined by lstat(2), not stat(2), though).

Yours,

    -mi

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Iain Hibbert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, 14 Apr 2009, Mikhail T. wrote:

> > i beg to differ. main process (the one that accepts connection) is
> > running with elevated privileges, yes.
> >From the security standpoint, this negates all/most benefits of having a
> dedicated UID for the service. The security people will tell you, that,

I agree too, its not good to run a daemon (that can be accessed over a
radio link and create/modify files no less) as root.

> I agree, that continuing to run as root after accepting connection is
> bad -- if a matching entry is not found, the server, indeed, ought to
> setuid to some non-root user (as set by the -u switch or determined from
> the ownership of the top-level itself). However, the above-mentioned
> cooperation may still have its uses for some people. That said, they can
> have all their BD_ADDR symlinks point to the same directory and
> cooperate there, so I don't feel strongly about it either.

If you did that, it would I think be better to have the bdaddr mapping in
a config file. Symlinks are too much trouble. On the other hand, I'm not
keen on config files either :)

Also, it could be better in that case to have a master daemon (along the
lines of inetd) that could accept connectins and start obex according to
the remote device address. Thats perhaps a lot of work though.

> > i also must say that we are trying to solve the problem at the wrong
> > level. more specifically, for phone book back up you probably want to
> > use something else (like sync-ml for example) not not obexapp.
> >
> Not sure, what "sync-ml" is (there is no such port).

Try "msynctool" which uses libopensync, it has a pluggable API for
different sync protocols (syncml is Nokia, synce is Windows) and is run
from the computer end so you wouldn't have any issues with incoming files.

> But what about dropping camera's pictures and videos? People would
> certainly expect to be able to do that straight from their devices
> (rather than by running a client of some sort), and find the files
> somewhere under their home directories (perhaps in ~/Desktop).

Do you want to send pictures to your account when your wife is logged in,
or does she want to when you are logged in?  I don't know what prior art
is there, but it seems to me that (as I said before) the person logged in
at the console owns the machine and should receive files being sent. As
Max said, Bluetooth is not big on credentials, it is assumed that all
users (normally a only one) have equal access.

For this reason, Bluetooth cannot properly be a multi-user link unless all
the users trust each other (while Alice is sending files to the computer,
Bill could be checking her phone log) so I don't see a problem with having
all the files in a master directory owned by the same user (but setting
the default path per remote device seems a good compromise)

regards,
iain

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Maksim Yevmenkin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/4/13 Mikhail T. <mi+thun@...>:

> Maksim Yevmenkin написав(ла):
>>> I think, Maksim's proposal is suboptimal, because the uploaded files end
>>> up owned by the new user obex, rather than the actual user (foo in the
>>> above example), which will make file-manipulations on the system itself
>>> more difficult (obex-owned will they not have 600 permissions?). It also
>>>
>> permissions on files will be set to 0660.
>>
> I didn't see, where you do this -- simply using mkstemp will result in
> 600. But it can be done, of course. However, it is still imperfect,

perhaps you should take a closer look at the patch i posted? :-) in server.c

@@ -565,6 +668,15 @@
  }
  }

+ if (chmod(context->temp, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) < 0) {
+ log_err("%s(): Could not chmod(%s). %s (%d)",
+ __func__, context->temp,
+ strerror(errno), errno);
+
+ codes = obexapp_util_errno2response(errno);
+ goto done;
+ }
+

> because all of the bluetooth users would have to be listed in obex'
> group and so there can be no more than 20 of them (I think, that's the
> limit on a group size).

not really, as i said in my original email user's private obex
directory is owned by 'obex' user, but the group is still set to the
user's group and permissions are set to 0770.

> In any case, being owned by the actual user seems far more
> straightforward...

its all about security vs. usability to me :) please read below.

>>> necessitates creation of a new UID without the security benefit of
>>> having the daemon run under that UID permanently (but only switching
>>> after accepting each connection)...
>>>
>> i beg to differ. main process (the one that accepts connection) is
>> running with elevated privileges, yes.
>
> From the security standpoint, this negates all/most benefits of having a
> dedicated UID for the service. The security people will tell you, that,
> as long as the root-owned process is always running and listening to
> connections, it can some day be fooled and so they don't like it anyway.

i'm having a hard time follow this part of the argument. both patches
(yours and mine) will accept connection with elevated privileges.
there is absolutely no difference here. so, i'm going to dismiss this
part of the argument, sorry :)

>> however, the process that
>> handles the actual connection from the client is running with reduced
>> privileges. so, there is a security benefit.
>
> It will drop the root-privileges under my proposal as well. It is just
> that the new UID will be that of the connecting user as determined by
> the BD_ADDR match, if such a match can be found. Otherwise, yes, it
> should become whatever user is specified with the -u switch.

if you are arguing that having separate 'obex' user provides no
security benefits, then i disagree. and here is why.

to me security is about managing the risks. i have to assume that
someone will break into someone's system using obexapp as attack
vector. so, lets see what happens in this case

(1) when obexapp is running as separate user 'obex' in chroot()ed
environment, the question is: what kind of damage 'obex' user can do
in chroot()ed environment?

(2) when obexapp is running as potentially _any_ user in the system in
_unrestricted_ environment, the question is: what kind of damage _any_
user can do while roaming free?

keep in mind that 'bad guy' can populate his environment with all kind
of files before obtaining shell.

now,  please put on your security person's hat and tell me honestly
which option would you choose?

>> i'm actually not feeling very strongly about this. my initial choice
>> is to be on a safe side. basically, what i'm trying to guard against
>> is when someone put a symlink owned by root into the obexapp root
>> folder. this is very easy thing to do, imo. i personally did it :)
>>
> The only thing I do feel strongly about, is that, when a matching
> directory entry is found, the server shall perform a setuid not to the
> generic 'obex' user, but to the owner of that entry (and chroot into it,
> yes).

like i said, its security vs. usability. i probably can live with
chroot()ing and changing uid to owner of the directory (and _not_
symlink).

> I do not think, you should give special meaning to entry named "default"
> -- because that would require special handling of the case, when
> somebody's BD_ADDR resolves to name "default". I'd say, it is Ok, if no
> match for the device is found, to remain in the top-level directory
> (after dropping the root-privileges). But, again, no strong feeling
> about this.

i'm willing to take my chances of this one :) its strictly local
configuration and if someone has, in fact, named his/her bluetooth
gadget 'default' then its too bad :) i'm also not keen of keeping
'default' name. it can be anything, like '00:00:00:00:00:00' or
whatever.

> My other ideas (such as the matching entries not necessarily being
> subdirectories) came from trying to maintain compatibility with the
> current operations (where everything lives in the same directory), while
> still allowing the created files to belong to different, cooperating users.

no, just put new behavior under separate option and keep it disabled
by default.

>> basically this type of misconfiguration will make obexapp continue to
>> run with elevated privileges while servicing clients requests and that
>> is a 'bad thing (tm)' :)
>>
> I agree, that continuing to run as root after accepting connection is
> bad -- if a matching entry is not found, the server, indeed, ought to
> setuid to some non-root user (as set by the -u switch or determined from
> the ownership of the top-level itself). However, the above-mentioned
> cooperation may still have its uses for some people. That said, they can
> have all their BD_ADDR symlinks point to the same directory and
> cooperate there, so I don't feel strongly about it either.

the 'default' virtual root stays. remote clients have no business to
see, know about and/or try to mess with other clients virtual roots.
not sure if you noticed, but 'default' virtual root can be also
considered as another level of access. basically, if there is no
'default' virtual root, clients without virtual root won't be able to
access the server.

broken symlinks is a bad idea, imo. i still do not get what do you
gain by changing ownership on files in the same directory. perhaps i'm
missing something here. please give me an example.

>> i also must say that we are trying to solve the problem at the wrong
>> level. more specifically, for phone book back up you probably want to
>> use something else (like sync-ml for example) not not obexapp.
>>
> Not sure, what "sync-ml" is (there is no such port). But what about

there is something called multisync (or something like that) but it
needs freebsd bluetooth plugin. basically sync-ml is a xml based
protocol that runs over obex and is used for synchronizing objects on
systems.

> dropping camera's pictures and videos? People would certainly expect to
> be able to do that straight from their devices (rather than by running a
> client of some sort), and find the files somewhere under their home
> directories (perhaps in ~/Desktop).

sure and they can do it.

> So, I agree with most of your change, except the UID part -- in case a
> subdirectory-entry with a matching name is found, the argument of the
> setuid() (and setgid()) call should be the UID (and GID) of the entry
> (as determined by lstat(2), not stat(2), though).

like i said, its probably ok to change uid to owner of the _directory_
and chroot() into it. but lstat(2) is out, sorry :)

thanks,
max
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Maksim Yevmenkin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, Apr 14, 2009 at 9:15 AM, Iain Hibbert <plunky@...> wrote:
> On Tue, 14 Apr 2009, Mikhail T. wrote:
>
>> > i beg to differ. main process (the one that accepts connection) is
>> > running with elevated privileges, yes.
>> >From the security standpoint, this negates all/most benefits of having a
>> dedicated UID for the service. The security people will tell you, that,
>
> I agree too, its not good to run a daemon (that can be accessed over a
> radio link and create/modify files no less) as root.

its only to call accept() and fork(). child process drops privileges
right after that. in fact, i believe, there is no network i/o
performed while child is running with elevated privileges. so, the
window is small here.

>> I agree, that continuing to run as root after accepting connection is
>> bad -- if a matching entry is not found, the server, indeed, ought to
>> setuid to some non-root user (as set by the -u switch or determined from
>> the ownership of the top-level itself). However, the above-mentioned
>> cooperation may still have its uses for some people. That said, they can
>> have all their BD_ADDR symlinks point to the same directory and
>> cooperate there, so I don't feel strongly about it either.
>
> If you did that, it would I think be better to have the bdaddr mapping in
> a config file. Symlinks are too much trouble. On the other hand, I'm not
> keen on config files either :)

as i suggested, in private email, something like apache's .htaccess
mechanism would be an ultimate solution here. however, its way too
much complicated for what obexapp is :-)

> Also, it could be better in that case to have a master daemon (along the
> lines of inetd) that could accept connectins and start obex according to
> the remote device address. Thats perhaps a lot of work though.

that's, actually, an interesting idea. i could see how it could be
applied to almost any bluetooth service. its not that much work, imo.
obexapp already can use stdin/out as file descriptors (in client
mode). configuration aspect of it is a pain though. perhaps we should
think along the lines of bluetooth inetd that maps pair (protocol,
protocol parameters) to service? something like (l2cap, 1) -> sdpd,
(rfcomm, 1) -> obexapp, (rfcomm, 3) -> rfcomm_pppd etc.?

>> But what about dropping camera's pictures and videos? People would
>> certainly expect to be able to do that straight from their devices
>> (rather than by running a client of some sort), and find the files
>> somewhere under their home directories (perhaps in ~/Desktop).
>
> Do you want to send pictures to your account when your wife is logged in,
> or does she want to when you are logged in?  I don't know what prior art
> is there, but it seems to me that (as I said before) the person logged in
> at the console owns the machine and should receive files being sent. As
> Max said, Bluetooth is not big on credentials, it is assumed that all
> users (normally a only one) have equal access.
>
> For this reason, Bluetooth cannot properly be a multi-user link unless all
> the users trust each other (while Alice is sending files to the computer,
> Bill could be checking her phone log) so I don't see a problem with having
> all the files in a master directory owned by the same user (but setting
> the default path per remote device seems a good compromise)

yes, that is what i was thinking too. its pretty much like running
multiple copies of obexapp without actually running multiple copies of
obexapp :)

thanks,
max


>
> regards,
> iain
>
>
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Maksim Yevmenkin написав(ла):
> 2009/4/13 Mikhail T. <mi+thun@...>:
>  
> not really, as i said in my original email user's private obex
> directory is owned by 'obex' user, but the group is still set to the
> user's group and permissions are set to 0770.
Even if the GID of the files will be that of the user, it being owned by
obex will cause inconvenience.
> i'm having a hard time follow this part of the argument. both patches
> (yours and mine) will accept connection with elevated privileges.
> there is absolutely no difference here. so, i'm going to dismiss this
> part of the argument, sorry :)
>  
You are absolutely correct, that there is no security difference between
our approaches, when a matching BD_ADDR entry is found. When one is not
found, the user to switch to can be the owner of the default/
subdirectory, for example -- I don't really care for this case.

>>> however, the process that
>>> handles the actual connection from the client is running with reduced
>>> privileges. so, there is a security benefit.
>>>      
>> It will drop the root-privileges under my proposal as well. It is just
>> that the new UID will be that of the connecting user as determined by
>> the BD_ADDR match, if such a match can be found. Otherwise, yes, it
>> should become whatever user is specified with the -u switch.
>>    
> if you are arguing that having separate 'obex' user provides no
> security benefits, then i disagree. and here is why.
>
> to me security is about managing the risks. i have to assume that
> someone will break into someone's system using obexapp as attack
> vector. so, lets see what happens in this case
>
> (1) when obexapp is running as separate user 'obex' in chroot()ed
> environment, the question is: what kind of damage 'obex' user can do
> in chroot()ed environment?
>
> (2) when obexapp is running as potentially _any_ user in the system in
> _unrestricted_ environment, the question is: what kind of damage _any_
> user can do while roaming free?
>  
I have already conceded in the previous e-mail(s), that I agree, that
chroot-ing into the found subdirectory is a good idea. So, it would not
"unrestricted" environment. The damage will be limited to the attacker's
full access to the user's designated subdirectory. And it will be
exactly the same as in your approach, because -- under your approach --
all of the files in the designated subdirectory will be obex-owned and
thus accessible to an obex' process.

>> The only thing I do feel strongly about, is that, when a matching
>> directory entry is found, the server shall perform a setuid not to the
>> generic 'obex' user, but to the owner of that entry (and chroot into it,
>> yes).
>>    
>
> like i said, its security vs. usability. i probably can live with
> chroot()ing and changing uid to owner of the directory (and _not_
> symlink).
>  
This is wrong. Consider:

    wallaby@tasmania (11) mkdir ~/bluetooth
    wallaby@tasmania (12) echo 'Please, map my ~wallaby/bluetooth to my
    device' | write root
    ...
    root@tasmania (713) ln -s ~wallaby/bluetooth
    /var/spool/obex/Wallaby-Blackerry
    root@tasmania (714) echo 'Done, enjoy!' | write wallaby
    ...
    wallaby@tasmania (13) rmdir ~/bluetooth
    wallaby@tasmania (14) ln -s ~wombat/bluetooth ~/bluetooh

Voila, because you trust stat(2) instead of lstat(2), Wallaby has just
gained full access to Wombat's bluetooth files -- and can switch to
anyone else's at will...

When you use lstat, you make it root's responsibility to chown the
BD_ADDR-symlinks under /var/spool/obex appropriately. Root may screw it
up (and you may want to reject connections, if a particular entry
belongs to root), but using stat(2) you give them no chance...
> broken symlinks is a bad idea, imo. i still do not get what do you
> gain by changing ownership on files in the same directory. perhaps i'm
> missing something here. please give me an example.
>  
Therein lies the problem -- the "broken symlinks" are a very useful
thing, but suffer from the negative connotations of the word "broken".
There is nothing wrong with them -- and /etc/make.conf provides a great
example. They are very convenient in that they can be read and written
in a single transaction (readlink(2) and symlink(2)) -- instead of
open(2), read(2)/write(2), close(2). Their content is immediately
readable with ls, and a directory containing them can also be modified
atomically (even from scripts: with readlink(1), rm, ln) without
locking. That's why "broken symlinks" aren't bad in general...

Now, back to the topic at hand, my plan would've been an improvement
over the current situation. Whereas the existing obexapp (and the new
one, because you insist on the new behavior being optional) would dump
everything into the same directory under the same ownership, my approach
would allow different files to belong to different users, even if they
still share the same directory.

For example, a group of photographers dropping off pictures into the
common area may want to use the same server-directory. But they would
still prefer to be able to distinguish, who made which picture.

That said, under my approach such multi-user sharing is still possible,
even if you insist on BD_ADDR-entries being directories:

    root@tasmania (817) mkdir /home/dropoff
    root@tasmania (818) chmod 1777 /home/dropoff
    root@tasmania (819) foreach cam (Wallaby Wombat Pademelon Thylacine)
    foreach? ln -s /home/dropoff /var/spool/$cam-Camera
    foreach? chown -h $cam /var/spool/$cam-Camera
    foreach? end

Under my proposal, the dropped-off pictures will belong to the proper
users, while all residing in the same directory (for the editors to
view). Under your proposal, such sharing would be far more involved to
set up for no extra security...

So, the only thing I insist on, is that lstat be used to determine the
UID to switch to (after chroot-ing), when a matching BD_ADDR (or
bt_hostname) is found.
> like i said, its probably ok to change uid to owner of the _directory_
> and chroot() into it. but lstat(2) is out, sorry :)
>  
Please, consider the above security example. stat is insecure for our
purpose, while lstat is just fine.

    -mi

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Iain Hibbert написав(ла):
> I agree too, its not good to run a daemon (that can be accessed over a
> radio link and create/modify files no less) as root.
>  
Both proposals being discussed currently presume the original daemon
running as root, dropping privileges only after forking. Whatever
mechanism is devised to avoid that, would be applicable to both, so lets
put this part "outside of the parentheses" :-)
> If you did that, it would I think be better to have the bdaddr mapping in
> a config file. Symlinks are too much trouble. On the other hand, I'm not
> keen on config files either :)
>  
Config-files are a far greater "evil". Their maintenance by more than
one person (or one with more than one terminal) requires locking, etc.
-- for no additional benefit. Just use `ls -l' instead of `cat'...
Symlinks (be they "broken" or not) can be maintained atomically and are
thus superior. And each record keeps the timestamp and other useful info...
>> But what about dropping camera's pictures and videos? People would certainly expect to be able to do that straight from their devices (rather than by running a client of some sort), and find the files somewhere under their home directories (perhaps in ~/Desktop).
>>    
>
> Do you want to send pictures to your account when your wife is logged in,
> or does she want to when you are logged in?
I don't see, how this is relevant. Everything, I and Maksim, are talking
about is equally applicable even to a completely headless server. In my
earlier e-mail (responding to Maksim), I give an example of a server set
up to accept media uploads from multiple photographers (think of the
guys with giant lenses around a football field, wirelessly pushing their
snaps to the single box, from which editors pick them up for
broadcasting/publishing nearly real-time) -- nobody needs to be
logged-in to the box itself for that to work...
> I don't know what prior art is there, but it seems to me that (as I said before) the person logged in at the console owns the machine and should receive files being sent.
I don't know, what you mean. The two of us (and the babysitter, BTW)
each have our own X-session, which are all started by KDM on demand.
Ctrl-Alt-F9 is, usually, me, Ctrl-Alt-F10 -- the better third, and
Ctrl-Alt-F11 -- whoever else needs access to their e-mail... None of
this is relevant, though, I think...
> For this reason, Bluetooth cannot properly be a multi-user link unless all the users trust each other (while Alice is sending files to the computer, Bill could be checking her phone log) so I don't see a problem with having all the files in a master directory owned by the same user (but setting the default path per remote device seems a good compromise)
>  
Yes, it is a good compromise. And it can go one step further towards
convenience (without compromising security), by using not just the
device-specific PATH, but also the device-specific UID/GID...

Yours,

    -mi

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Maksim Yevmenkin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/4/14 Mikhail T. <mi+thun@...>:
> Maksim Yevmenkin написав(ла):
>> 2009/4/13 Mikhail T. <mi+thun@...>:
>>
>> not really, as i said in my original email user's private obex
>> directory is owned by 'obex' user, but the group is still set to the
>> user's group and permissions are set to 0770.
>
> Even if the GID of the files will be that of the user, it being owned by
> obex will cause inconvenience.

something's gotta give :) can't please everybody :)

[...]

>>>> however, the process that
>>>> handles the actual connection from the client is running with reduced
>>>> privileges. so, there is a security benefit.
>>>>
>>> It will drop the root-privileges under my proposal as well. It is just
>>> that the new UID will be that of the connecting user as determined by
>>> the BD_ADDR match, if such a match can be found. Otherwise, yes, it
>>> should become whatever user is specified with the -u switch.
>>>
>> if you are arguing that having separate 'obex' user provides no
>> security benefits, then i disagree. and here is why.
>>
>> to me security is about managing the risks. i have to assume that
>> someone will break into someone's system using obexapp as attack
>> vector. so, lets see what happens in this case
>>
>> (1) when obexapp is running as separate user 'obex' in chroot()ed
>> environment, the question is: what kind of damage 'obex' user can do
>> in chroot()ed environment?
>>
>> (2) when obexapp is running as potentially _any_ user in the system in
>> _unrestricted_ environment, the question is: what kind of damage _any_
>> user can do while roaming free?
>>
> I have already conceded in the previous e-mail(s), that I agree, that
> chroot-ing into the found subdirectory is a good idea. So, it would not
> "unrestricted" environment. The damage will be limited to the attacker's
> full access to the user's designated subdirectory. And it will be
> exactly the same as in your approach, because -- under your approach --
> all of the files in the designated subdirectory will be obex-owned and
> thus accessible to an obex' process.

ah, not exactly. its not only the files that 'bad guy' can upload into
(possibly chroot()ed) environment. its the user id. for example, what
if certain user id has access to a certain device node? 'bad guy'
could just mknod(8) device node and ...

>>> The only thing I do feel strongly about, is that, when a matching
>>> directory entry is found, the server shall perform a setuid not to the
>>> generic 'obex' user, but to the owner of that entry (and chroot into it,
>>> yes).
>>
>> like i said, its security vs. usability. i probably can live with
>> chroot()ing and changing uid to owner of the directory (and _not_
>> symlink).
>>
> This is wrong. Consider:
>
>    wallaby@tasmania (11) mkdir ~/bluetooth
>    wallaby@tasmania (12) echo 'Please, map my ~wallaby/bluetooth to my
>    device' | write root
>    ...
>    root@tasmania (713) ln -s ~wallaby/bluetooth
>    /var/spool/obex/Wallaby-Blackerry
>    root@tasmania (714) echo 'Done, enjoy!' | write wallaby
>    ...
>    wallaby@tasmania (13) rmdir ~/bluetooth
>    wallaby@tasmania (14) ln -s ~wombat/bluetooth ~/bluetooh
>
> Voila, because you trust stat(2) instead of lstat(2), Wallaby has just
> gained full access to Wombat's bluetooth files -- and can switch to
> anyone else's at will...

hmm.... perhaps, i'm missing something here.  here is what i did

== step 1 ==

%id
uid=1004(wallaby) gid=1004(wallaby) groups=1004(wallaby)

%mkdir ~/bluetooth

%ls -l
drwxr-xr-x  2 wallaby  wallaby  512 Apr 14 11:20 bluetooth

== step 2 ==

beetle# pwd
/var/spool/obex

beetle# ln -s ~wallaby/bluetooth Wallaby-Blackerry

beetle# ls -l
lrwxr-xr-x   1 root  obex    23 Apr 14 11:21 Wallaby-Blackerry ->
/home/wallaby/bluetooth

beetle# stat -L Wallaby-Blackerry
99 1490343 drwxr-xr-x 2 wallaby wallaby 5953437 512 "Apr 14 11:20:37
2009" "Apr 14 11:20:37 2009" "Apr 14 11:20:37 2009" "Apr 14 11:20:37
2009" 4096 4 0 Wallaby-Blackerry

so as you can see user/group ids are correct, i.e. wallaby/wallaby

== step 3 ==

%id
uid=1005(wombat) gid=1005(wombat) groups=1005(wombat)

%mkdir ~/bluetooth

%ls -l
drwxr-xr-x  2 wombat  wombat  512 Apr 14 11:22 bluetooth

== step 4 ==

%id
uid=1004(wallaby) gid=1004(wallaby) groups=1004(wallaby)

%pwd
/usr/home/wallaby

%rmdir bluetooth/

%ln -s ~wombat/bluetooth ~/bluetooth

%ls -l
lrwxr-xr-x  1 wallaby  wallaby  22 Apr 14 11:29 bluetooth ->
/home/wombat/bluetooth

== step 5 ==

beetle# pwd
/var/spool/obex

beetle# stat -L Wallaby-Blackerry
99 1490434 drwxr-xr-x 2 wombat wombat 5953822 512 "Apr 14 11:22:10
2009" "Apr 14 11:22:10 2009" "Apr 14 11:22:10 2009" "Apr 14 11:22:10
2009" 4096 4 0 Wallaby-Blackerry

so, as you can see user/group ids are still correct, i.e. wombat/wombat.

also i used stat -L which makes use of stat(2) instead of lstat(2). so
from what i can see, and please feel free to correct me if i wrong,
user wallaby just intentionally 'gave up' his/her files to user
'wombat'. i do not see any problem here, do you? or am i missing
something obvious here?

> When you use lstat, you make it root's responsibility to chown the
> BD_ADDR-symlinks under /var/spool/obex appropriately. Root may screw it
> up (and you may want to reject connections, if a particular entry
> belongs to root), but using stat(2) you give them no chance...

if 'root' screws up, then game is over :) period. you can make this
argument with any piece of software out there :)

>> broken symlinks is a bad idea, imo. i still do not get what do you
>> gain by changing ownership on files in the same directory. perhaps i'm
>> missing something here. please give me an example.
>>
> Therein lies the problem -- the "broken symlinks" are a very useful
> thing, but suffer from the negative connotations of the word "broken".
> There is nothing wrong with them -- and /etc/make.conf provides a great
> example. They are very convenient in that they can be read and written

please let it go already :) i heard your point about /etc/malloc.conf
several times. you made it loud and clear. just because someone did it
this way, does not mean the the same model should be applied for
everything else. i'm sure whoever did this had good reasons for doing
it this way. keep in mind that someone else (or possibly the same
person) provided MALLOC_OPTIONS environmental variable and
_malloc_options global variable to override /etc/malloc.conf. imo, its
fine to use 'broken' symlinks to pass a few characters, however, you
suggesting to use the same model for something that is more
complicated. there probably are people who are confused about
permission on symlink vs. permissions on the directory symlink points
to. i was one of those people in not too distant past :-)

> in a single transaction (readlink(2) and symlink(2)) -- instead of
> open(2), read(2)/write(2), close(2). Their content is immediately
> readable with ls, and a directory containing them can also be modified
> atomically (even from scripts: with readlink(1), rm, ln) without
> locking. That's why "broken symlinks" aren't bad in general...

ok, 'broken' symlinks are bad idea, imo, when used as access control
mechanism :)

> Now, back to the topic at hand, my plan would've been an improvement
> over the current situation. Whereas the existing obexapp (and the new
> one, because you insist on the new behavior being optional) would dump
> everything into the same directory under the same ownership, my approach
> would allow different files to belong to different users, even if they
> still share the same directory.
>
> For example, a group of photographers dropping off pictures into the
> common area may want to use the same server-directory. But they would
> still prefer to be able to distinguish, who made which picture.

bad example - meta data in the pictures themselves tell much better story :)

> That said, under my approach such multi-user sharing is still possible,
> even if you insist on BD_ADDR-entries being directories:
>
>    root@tasmania (817) mkdir /home/dropoff
>    root@tasmania (818) chmod 1777 /home/dropoff
>    root@tasmania (819) foreach cam (Wallaby Wombat Pademelon Thylacine)
>    foreach? ln -s /home/dropoff /var/spool/$cam-Camera
>    foreach? chown -h $cam /var/spool/$cam-Camera
>    foreach? end
>
> Under my proposal, the dropped-off pictures will belong to the proper
> users, while all residing in the same directory (for the editors to
> view). Under your proposal, such sharing would be far more involved to
> set up for no extra security...

again, bad example, imo. all pictures will end up in /home/dropoff
owned by the same user (either 'obex' or owner of '/home/dropoff').
just point editors to /home/dropoff instead of /var/spool/obex and be
done with it. the only difference is that all the files will be owned
by the same user, but like i said, meta data in the pictures will tell
far better story then user id :) i also do not understand why 'sticky
bit' is required (its only needed in your version of the patch).

> So, the only thing I insist on, is that lstat be used to determine the
> UID to switch to (after chroot-ing), when a matching BD_ADDR (or
> bt_hostname) is found.

please see my example above.

>> like i said, its probably ok to change uid to owner of the _directory_
>> and chroot() into it. but lstat(2) is out, sorry :)
>>
> Please, consider the above security example. stat is insecure for our
> purpose, while lstat is just fine.

hmm, for my example above

beetle# stat  Wallaby-Blackerry
98 47348 lrwxr-xr-x 1 root obex 1836017711 23 "Apr 14 11:21:23 2009"
"Apr 14 11:21:23 2009" "Apr 14 11:21:23 2009" "Apr 14 11:21:23 2009"
4096 0 0 Wallaby-Blackerry

and (with trailing /)

beetle# stat Wallaby-Blackerry/
99 1490343 lrwxr-xr-x 1 wallaby wallaby 1836017711 22 "Apr 14 11:29:08
2009" "Apr 14 11:29:08 2009" "Apr 14 11:29:08 2009" "Apr 14 11:29:08
2009" 4096 0 0 Wallaby-Blackerry/

stat(1)  _without_ '-L' option uses lstat(2).

thanks,
max
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Maksim Yevmenkin написав(ла):
> something's gotta give :) can't please everybody :)
>  
You can make sure, the uploaded files belong to the owner of the device,
that uploaded them.

>> I have already conceded in the previous e-mail(s), that I agree, that
>> chroot-ing into the found subdirectory is a good idea. So, it would not
>> "unrestricted" environment. The damage will be limited to the attacker's
>> full access to the user's designated subdirectory. And it will be
>> exactly the same as in your approach, because -- under your approach --
>> all of the files in the designated subdirectory will be obex-owned and
>> thus accessible to an obex' process.
>>    
>
> ah, not exactly. its not only the files that 'bad guy' can upload into
> (possibly chroot()ed) environment. its the user id. for example, what
> if certain user id has access to a certain device node? 'bad guy'
> could just mknod(8) device node and ...
>  
First of all, mknod(8) utility is deprecated on modern FreeBSD systems
-- in favor of devfs. So, you are worried, that a bad guy will
impersonate wallaby and access a wallaby-owned device? I don't think,
this is possible in default FreeBSD installations. And admins granting
some users direct access to devices may chose to limit remote access to
these user accounts.
> beetle# stat -L Wallaby-Blackerry
> 99 1490434 drwxr-xr-x 2 wombat wombat 5953822 512 "Apr 14 11:22:10
> 2009" "Apr 14 11:22:10 2009" "Apr 14 11:22:10 2009" "Apr 14 11:22:10
> 2009" 4096 4 0 Wallaby-Blackerry
>
> so, as you can see user/group ids are still correct, i.e. wombat/wombat.
>  
Wombat UID for Wallaby-Blackberry is NOT correct!
> also i used stat -L which makes use of stat(2) instead of lstat(2). so
> from what i can see, and please feel free to correct me if i wrong,
> user wallaby just intentionally 'gave up' his/her files to user
> 'wombat'. i do not see any problem here, do you? or am i missing
> something obvious here?
>  
Yes, exactly as above! User of Wallaby-Blackberry will connect and --
depending on their own choice -- have full access to Wombat's files,
because stat will tell obexapp, to use UID of wombat, whereas lstat
would've told it to use the UID of Wallaby (and fail to access Wombat's
600-moded files).

In fact, because Wallaby is free to make their own ~/bluetooth a symlink
to ANYTHING, they may get access to ANYBODY's files, even those of
users, who don't use Bluetooth. Once root sets up
/var/spool/obex/Wallaby-Blackberry pointing at /home/wallaby/bluetooth,
user Wallaby can change that link to anything -- except, perhaps, root
themselves...
>> When you use lstat, you make it root's responsibility to chown the
>> BD_ADDR-symlinks under /var/spool/obex appropriately. Root may screw it
>> up (and you may want to reject connections, if a particular entry
>> belongs to root), but using stat(2) you give them no chance...
>>    

> if 'root' screws up, then game is over :) period. you can make this argument with any piece of software out there :)
>  
I agree. Which is why I keep saying, you should be using lstat (to read
info on entries created by root  under /var/spool/obex), instead of stat
(which would give you info on entries maintained by the -- potentially
malicious -- users).
> there probably are people who are confused about
> permission on symlink vs. permissions on the directory symlink points
> to. i was one of those people in not too distant past :-)
>  
Didn't we just agree, that root being confused is a "game-over" and
shall not be mentioned?
>> That's why "broken symlinks" aren't bad in general...
>>    
> ok, 'broken' symlinks are bad idea, imo, when used as access control
> mechanism :)
>  
Slow, painful, but still progress... :-)
>> For example, a group of photographers dropping off pictures into the
>> common area may want to use the same server-directory. But they would
>> still prefer to be able to distinguish, who made which picture.
>>    
>
> bad example - meta data in the pictures themselves tell much better story :)
>  
You are nit-picking, but no, actually. The EXIF metadata (BTW, relying
on file-format specific metadata to provide information, that filesystem
itself can/should provide, seems wrong in itsefl) will give the camera's
model and the time of the shot, but not the owner... It does not matter,
again, because multiple BD_ADDR symlinks can still point to the same
directory.

>> That said, under my approach such multi-user sharing is still possible,
>> even if you insist on BD_ADDR-entries being directories:
>>
>>    root@tasmania (817) mkdir /home/dropoff
>>    root@tasmania (818) chmod 1777 /home/dropoff
>>    root@tasmania (819) foreach cam (Wallaby Wombat Pademelon Thylacine)
>>    foreach? ln -s /home/dropoff /var/spool/$cam-Camera
>>    foreach? chown -h $cam /var/spool/$cam-Camera
>>    foreach? end
>>
>> Under my proposal, the dropped-off pictures will belong to the proper
>> users, while all residing in the same directory (for the editors to
>> view). Under your proposal, such sharing would be far more involved to
>> set up for no extra security...
>>    
>
> again, bad example, imo. all pictures will end up in /home/dropoff
> owned by the same user (either 'obex' or owner of '/home/dropoff').
>  
They will under YOUR proposal (using stat). Under mine (using lstat),
the files will have different owning UIDs... Which is good :-)
You may not like a particular example, but you have to admit, that my
proposal gives more flexibility to the admin setting up BT-access. They
can, if they want to, allow meaningful directory-sharing for the files
belonging to different users. And if they don't want to, they can keep
all symlinks pointing to /home/dropoff belong to `obex' (or whoever).

Under your proposal, there is no such flexibility and yet it is not any
more secure (sorry, mknod is too superficial). Escaping from chroot is
never easy, and for non-root users it is impossible -- without bugs in
the kernel...

> just point editors to /home/dropoff instead of /var/spool/obex and be done with it.
Of course, the editors would be looking at /home/dropoff! I don't even
understand, how what I wrote could've been read differently. The editors
will be looking at /home/dropoff (or, more likely, something like
\\dropoff\dropoff\). And in there they will be able to group files by
users (owners of the matching entries under /var/spool/obex) -- if you
take my approach (lstat). Under your approach (stat), the user would be
the same (owner of /home/dropoff)...
> i also do not understand why 'sticky bit' is required (its only needed in your version of the patch).
>  
It is not required -- only to prevent people from (accidentally,
perhaps) overwriting each other's files under certain circumstances.

To summarize, you seem willing to consider the owner of the matching
entry when determining, which UID to switch to when dropping
root-privileges after chroot. The only remaining disagreement is whether
to use lstat vs. stat for the purpose. It being, literally, a
one-character change in the code, you can go ahead and begin coding the
change to match your style preferences.

In the mean time, consider the example I just gave, showing stat being a
security hole...

Yours,

    -mi

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Maksim Yevmenkin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/4/14 Mikhail T. <mi+thun@...>:

[...]

> Slow, painful, but still progress... :-)

please find attached revised patch that implements mi's (aka Mikhail)
initial suggestion, i.e. use lstat(2) instead of stat(2). i've also
changed it a bit to allow both cases, i.e.

(1) when virtual root folder is requested and -u <user> option is set,
obexapp will always run as <user>;

(2) when virtual root folder is requested and _no_ -u option was
specified, obexapp will run as the owner of the found virtual root
folder entry (where entry is either symlink or actual subdirectory
under default root folder);

i've also included a patch, submitted by Ronald Klop to disable
spinner in client mode for non-interactive client sessions.

[...]

> To summarize, you seem willing to consider the owner of the matching
> entry when determining, which UID to switch to when dropping
> root-privileges after chroot. The only remaining disagreement is whether
> to use lstat vs. stat for the purpose. It being, literally, a
> one-character change in the code, you can go ahead and begin coding the
> change to match your style preferences.
>
> In the mean time, consider the example I just gave, showing stat being a
> security hole...

yes, now i get it :) sorry for being such a bonehead :) hopefully the
latest patch will work for everyone.

thanks,
max

Index: event.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/event.c,v
retrieving revision 1.6
diff -u -r1.6 event.c
--- event.c 5 Jan 2009 16:37:25 -0000 1.6
+++ event.c 14 Apr 2009 21:23:16 -0000
@@ -1,7 +1,7 @@
 /*
  * event.c
  *
- * Copyright (c) 2002 Maksim Yevmenkin <m_evmenkin@...>
+ * Copyright (c) 2002-2009 Maksim Yevmenkin <m_evmenkin@...>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -32,6 +32,7 @@
 #include <bluetooth.h>
 #include <obex.h>
 #include <stdio.h>
+#include <unistd.h>
 
 #include "compat.h"
 #include "obexapp.h"
@@ -131,7 +132,7 @@
 
  log_debug("%s(): Made some progress...", __func__);
 
- if (!context->server) {
+ if (!context->server && !context->ni && isatty(STDOUT_FILENO)) {
  static char spinner[] = "\\|/-";
  static uint32_t spinner_idx = 0;
 
Index: main.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/main.c,v
retrieving revision 1.13
diff -u -r1.13 main.c
--- main.c 23 Apr 2007 18:29:18 -0000 1.13
+++ main.c 14 Apr 2009 21:23:38 -0000
@@ -1,7 +1,7 @@
 /*
  * main.c
  *
- * Copyright (c) 2002 Maksim Yevmenkin <m_evmenkin@...>
+ * Copyright (c) 2002-2009 Maksim Yevmenkin <m_evmenkin@...>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -65,7 +65,7 @@
 {
  struct sigaction sa;
  char *ep = NULL, *pri_name = NULL;
- int n, service, noninteractive;
+ int n, service, detach;
  context_t context;
  obex_ctrans_t custfunc;
 
@@ -83,7 +83,7 @@
  /* Prepare context */
  memset(&context, 0, sizeof(context));
  context.tfd = context.sfd = -1;
- context.detach = 1;
+ detach = 1;
 
  context.ls_size = OBEXAPP_BUFFER_SIZE;
  if ((context.ls = (char *) malloc(context.ls_size)) == NULL)
@@ -118,8 +118,8 @@
  custfunc.customdata = &context;
 
  /* Process command line options */
- service = noninteractive = 0;
- while ((n = getopt(argc, argv, "a:A:cC:dDfhl:m:nr:Ssu:")) != -1) {
+ service = 0;
+ while ((n = getopt(argc, argv, "a:A:cC:dDfhl:m:nr:RsSu:")) != -1) {
  switch (n) {
  case 'a':
  if (!bt_aton(optarg, &context.raddr)) {
@@ -180,7 +180,7 @@
  break;
 
  case 'd': /* do not detach server */
- context.detach = 0;
+ detach = 0;
  break;
 
  case 'D': /* use stdin/stdout */
@@ -209,7 +209,7 @@
  usage(basename(argv[0]));
  /* NOT REACHED */
 
- noninteractive = 1;
+ context.ni = 1;
  break;
 
  case 'r': /* root */
@@ -217,8 +217,13 @@
  err(1, "Could not realpath(%s)", optarg);
  break;
 
+ case 'R': /* virtualize root for each device */
+ context.vroot = 1;
+ context.secure = 1;
+ break;
+
  case 's': /* server */
- if (noninteractive)
+ if (context.ni)
  usage(basename(argv[0]));
  /* NOT REACHED */
 
@@ -269,23 +274,10 @@
  log_open("obexapp", pri_name, 0);
 
  /* Detach server (if required) */
- if (context.server && context.detach) {
- pid_t pid = fork();
-
- if (pid == (pid_t) -1) {
- log_err("%s(): Could not fork. %s (%d)",
- __func__, strerror(errno), errno);
- exit(1);
- }
-
- if (pid != 0)
- exit(0);
-
- if (daemon(0, 0) < 0) {
- log_err("%s(): Could not daemon. %s (%d)",
- __func__, strerror(errno), errno);
- exit(1);
- }
+ if (context.server && detach && daemon(0, 0) < 0) {
+ log_err("%s(): Could not daemon. %s (%d)",
+ __func__, strerror(errno), errno);
+ exit(1);
  }
 
  /* Initialize OBEX */
@@ -305,7 +297,7 @@
 
  if (context.server)
  n = obexapp_server(context.handle);
- else if (noninteractive)
+ else if (context.ni)
  n = obexapp_non_interactive_client(context.handle, argc, argv);
  else
  n = obexapp_client(context.handle);
Index: obexapp.1
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/obexapp.1,v
retrieving revision 1.15
diff -u -r1.15 obexapp.1
--- obexapp.1 21 May 2007 15:55:35 -0000 1.15
+++ obexapp.1 14 Apr 2009 21:24:08 -0000
@@ -1,6 +1,6 @@
 .\" obexapp.1
 .\"
-.\" Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@...>
+.\" Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@...>
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -27,7 +27,7 @@
 .\" $Id: obexapp.1,v 1.15 2007/05/21 15:55:35 max Exp $
 .\" $FreeBSD$
 .\"
-.Dd April 10, 2007
+.Dd April 14, 2009
 .Dt OBEXAPP 1
 .Os
 .Sh NAME
@@ -54,7 +54,7 @@
 .Ar parameters
 .Nm
 .Fl s
-.Op Fl dDSh
+.Op Fl dDSRh
 .Op Fl A Ar BD_ADDR
 .Fl C Ar channel
 .Op Fl m Ar MTU
@@ -193,6 +193,12 @@
 Defaults to the maximum supported value.
 .It Fl n
 Work in the non-interactive client mode.
+.It Fl R
+Virtualize root folder for each client device in server mode.
+Will automatically turn on secure mode, i.e.
+.Fl S
+option.
+Please read section below for a complete description.
 .It Fl r Ar path
 Specify root folder.
 Default root folder in the server mode is
@@ -216,6 +222,57 @@
 The value specified may be either a username or a numeric user id.
 This only works if server was started as root.
 .El
+.Sh VIRTUAL ROOT FOLDERS
+When accepting connections in server mode,
+.Nm
+will attempt to find an entry that would act as a virtual root
+folder for the connecting device.
+Virtual root folders must reside under default root folder which is set
+with
+.Fl r
+option.
+The rules are as follows:
+.Bl -enum -offset indent -compact
+.It
+.Nm
+will try to resolve connecting device's BD_ADDR using
+.Xr bt_gethostbyaddr 3
+call and check for an entry that matches resolved name (if any);
+.It
+.Nm
+will check for an entry that matches connecting device's BD_ADDR;
+.It
+.Nm
+will check for an entry, named
+.Dq default ;
+.El
+If none of the above matches, then the connection to the client is terminated.
+Otherwise,
+.Nm
+will try to change default root folder the the found entry.
+.Pp
+If
+.Fl u
+option was specified, the
+.Nm
+will try to change to the specified user.
+Otherwise
+.Nm
+will try change to the user, that owns the found entry.
+That is, if the found entry is a symlink, the
+.Nm
+will try change to the user, that owns symlink and not to the user, that
+owns the entry symlink points to.
+.Pp
+This allows the same system to intelligently distinguish different
+client devices as belonging to different users.
+An administrator can set up the subdirectories for
+known devices under
+.Pa /var/spool/obex
+(or wherever, see
+.Fl r
+option) for each user, or even as symlinks to each user's home directory
+(or a subdirectory thereof).
 .Sh LOCALE SUPPORT
 The
 .Nm
@@ -325,6 +382,13 @@
 .Dv ANY
 address and RFCOMM channel
 .Li 1 .
+.It ln -s Ar /home/wallaby Ar /var/spool/obex/00:01:02:03:04:05
+.It chown -h wallaby Ar /var/spool/obex/00:01:02:03:04:05
+Whenever the device with BD_ADDR of 00:01:02:03:04:05 connects,
+.Nm
+running in server mode will switch to user ID
+.Ar wallaby
+and use their home directory as the top-level for the connection.
 .El
 .Ss Level 1 Information Access
 The first level involves the basic ability to put an object (such as a vCard)
Index: obexapp.h
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/obexapp.h,v
retrieving revision 1.9
diff -u -r1.9 obexapp.h
--- obexapp.h 23 Apr 2007 18:29:18 -0000 1.9
+++ obexapp.h 14 Apr 2009 21:26:44 -0000
@@ -1,7 +1,7 @@
 /*
  * obexapp.h
  *
- * Copyright (c) 2002 Maksim Yevmenkin <m_evmenkin@...>
+ * Copyright (c) 2002-2009 Maksim Yevmenkin <m_evmenkin@...>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -87,9 +87,10 @@
  unsigned server     : 1; /* server mode? */
  unsigned secure     : 1; /* secure mode? */
  unsigned done       : 1; /* done? */
- unsigned detach     : 1; /* detach server? */
  unsigned fbs        : 1; /* Folder Browsing Service */
- unsigned reserved   : 2;
+ unsigned vroot    : 1; /* virtualize device's root */
+ unsigned ni         : 1; /* non-interactive? */
+ unsigned reserved   : 1;
 
  /* local SDP session (server only) */
  void *ss;
@@ -111,6 +112,10 @@
  uint8_t *sbuffer;
 
  int mtu;            /* OBEX MTU */
+
+ /* credentials */
+ uid_t uid;
+ gid_t gid;
 };
 typedef struct context context_t;
 typedef struct context * context_p;
Index: server.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/server.c,v
retrieving revision 1.11
diff -u -r1.11 server.c
--- server.c 9 Apr 2009 23:16:31 -0000 1.11
+++ server.c 14 Apr 2009 20:55:37 -0000
@@ -1,7 +1,7 @@
 /*
  * server.c
  *
- * Copyright (c) 2002 Maksim Yevmenkin <m_evmenkin@...>
+ * Copyright (c) 2002-2009 Maksim Yevmenkin <m_evmenkin@...>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -89,6 +89,10 @@
 static char const * const ls_parent_folder =
  "<parent-folder/>\n";
 
+static int obexapp_server_set_initial_root (context_p context);
+static int obexapp_server_set_device_root  (context_p context);
+static int obexapp_server_set_final_root   (context_p context);
+
 /* OBEX request handlers */
 static obexapp_request_handler_t obexapp_server_request_connect;
 static obexapp_request_handler_t obexapp_server_request_disconnect;
@@ -114,7 +118,6 @@
 obexapp_server(obex_t *handle)
 {
  context_p context = (context_p) OBEX_GetUserData(handle);
- struct passwd *pw = NULL;
  int error = -1;
  struct sockaddr_rfcomm addr;
 
@@ -131,26 +134,6 @@
  goto done;
  }
 
- if (context->user != NULL) {
- if (atoi(context->user) != 0)
- pw = getpwuid(atoi(context->user));
- else
- pw = getpwnam(context->user);
-
- if (pw == NULL) {
- log_err("%s(): Unknown user %s", __func__,
- context->user);
- goto done;
- }
- }
-
- if (context->root[0] == '\0') {
- if (pw == NULL)
- strlcpy(context->root, OBEXAPP_ROOT_DIR, PATH_MAX);
- else
- strlcpy(context->root, pw->pw_dir, PATH_MAX);
- }
-
  log_info("%s: Starting OBEX server", __func__);
 
  if (OBEX_SetTransportMTU(handle, context->mtu, context->mtu) < 0) {
@@ -162,7 +145,7 @@
  addr.rfcomm_len = sizeof(addr);
  addr.rfcomm_family = AF_BLUETOOTH;
  addr.rfcomm_channel = context->channel;
- memcpy(&addr.rfcomm_bdaddr, &context->raddr, sizeof(context->raddr));
+ memcpy(&addr.rfcomm_bdaddr, &context->laddr, sizeof(context->laddr));
 
  if (OBEX_ServerRegister(handle, (struct sockaddr *) &addr,
  sizeof(addr)) < 0) {
@@ -170,40 +153,12 @@
  goto done;
  }
 
- if (getuid() == 0) {
- if (context->secure) {
- if (chroot(context->root) < 0) {
- log_err("%s(): Could not chroot(%s). %s (%d)",
- __func__, context->root,
- strerror(errno), errno);
- goto done;
- }
-
- strlcpy(context->root, "/", PATH_MAX);
- }
-
- if (pw != NULL) {
- if (setgid(pw->pw_gid) < 0) {
- log_err("%s(): Could not setgid(%d). %s (%d)",
- __func__, pw->pw_gid, strerror(errno),
- errno);
- goto done;
- }
-
- if (setuid(pw->pw_uid) < 0) {
- log_err("%s(): Could not setuid(%d). %s (%d)",
- __func__, pw->pw_uid, strerror(errno),
- errno);
- goto done;
- }
- }
- }
-
- if (chdir(context->root) < 0) {
- log_err("%s(): Could not chdir(%s). %s (%d)",
- __func__, context->root, strerror(errno), errno);
+ if (obexapp_server_set_initial_root(context) < 0)
+ goto done;
+ if (context->vroot && obexapp_server_set_device_root(context) < 0)
+ goto done;
+ if (obexapp_server_set_final_root(context) < 0)
  goto done;
- }
 
  log_debug("%s(): Entering event processing loop...", __func__);
 
@@ -227,6 +182,165 @@
 } /* obexapp_server */
 
 /*
+ * Set initial server root
+ */
+
+static int
+obexapp_server_set_initial_root(context_p context)
+{
+ struct passwd *pw = NULL;
+ char *ep;
+
+ if (context->user != NULL) {
+ context->uid = strtoul(context->user, &ep, 10);
+ if (*ep != '\0')
+ pw = getpwnam(context->user);
+ else
+ pw = getpwuid(context->uid);
+
+ if (pw == NULL) {
+ log_err("%s(): Unknown user '%s'",
+ __func__, context->user);
+ return (-1);
+ }
+
+ log_debug("%s(): Requested to run as '%s', uid=%d, gid=%d",
+ __func__, context->user, pw->pw_uid, pw->pw_gid);
+
+ context->uid = pw->pw_uid;
+ context->gid = pw->pw_gid;
+ } else {
+ context->uid = getuid();
+ context->gid = getgid();
+ }
+
+ /* Set default root */
+ if (context->root[0] == '\0') {
+ if (pw == NULL)
+ strlcpy(context->root, OBEXAPP_ROOT_DIR, PATH_MAX);
+ else
+ strlcpy(context->root, pw->pw_dir, PATH_MAX);
+ }
+
+ if (chdir(context->root) < 0) {
+ log_err("%s(): Could not chdir(%s). %s (%d)",
+ __func__, context->root, strerror(errno), errno);
+ return (-1);
+ }
+
+ log_debug("%s(): Using initial root %s", __func__, context->root);
+
+ return (0);
+} /* obexapp_server_set_initial_root */
+
+/*
+ * Set device specific server root
+ */
+
+static int
+obexapp_server_set_device_root(context_p context)
+{
+ char const *root[] = { NULL, NULL, NULL };
+ struct hostent *he;
+ struct stat sb;
+ int n;
+
+ n = 0;
+
+ he = bt_gethostbyaddr((char const *) &context->raddr,
+ sizeof(bdaddr_t), AF_BLUETOOTH);
+ if (he != NULL)
+ root[n ++] = (char const *) he->h_name;
+
+ root[n ++] = bt_ntoa(&context->raddr, NULL);
+
+ root[n ++] = "default";
+
+ for (n = 0; n < 3; n ++) {
+ if (root[n] == NULL)
+ break;
+
+ log_debug("%s(): Checking for %s/%s subdirectory",
+ __func__, context->root, root[n]);
+
+ if (lstat(root[n], &sb) < 0) {
+ if (errno == ENOENT)
+ continue;
+
+ log_err("%s(): Could not lstat(%s/%s). %s (%d)",
+ __func__, context->root, root[n],
+ strerror(errno), errno);
+
+ return (-1);
+ }
+
+ strlcat(context->root, "/", PATH_MAX);
+ strlcat(context->root, root[n], PATH_MAX);
+
+ if (chdir(root[n]) < 0) {
+ log_err("%s(): Could not chdir(%s). %s (%d)",
+ __func__, context->root, strerror(errno),
+ errno);
+ return (-1);
+ }
+
+ /* If user was not set before, take it from lstat() data */
+ if (context->user == NULL) {
+ context->uid = sb.st_uid;
+ context->gid = sb.st_gid;
+ }
+
+ log_debug("%s(): Using device specific root %s, uid=%d, gid=%d",
+ __func__, context->root, context->uid, context->gid);
+
+ return (1);
+ }
+
+ log_err("%s(): Could not find device specific root for the device " \
+ "bdaddr %s (%s)", __func__, root[1],
+ root[0]? root[0] : "-no-name-");
+
+ return (-1);
+} /* obexapp_server_set_device_root */
+
+/*
+ * Finalize server root
+ */
+
+static int
+obexapp_server_set_final_root(context_p context)
+{
+ if (context->secure) {
+ if (chroot(context->root) < 0) {
+ log_err("%s(): Could not chroot(%s). %s (%d)",
+ __func__, context->root,
+ strerror(errno), errno);
+ return (-1);
+ }
+
+ strlcpy(context->root, "/", PATH_MAX);
+ }
+
+ if (context->gid != getgid() && setgid(context->gid) < 0) {
+ log_err("%s(): Could not setgid(%d). %s (%d)",
+ __func__, context->gid, strerror(errno), errno);
+ return (-1);
+ }
+
+ if (context->uid != getuid() && setuid(context->uid) < 0) {
+ log_err("%s(): Could not setuid(%d). %s (%d)",
+ __func__, context->uid, strerror(errno), errno);
+ return (-1);
+ }
+
+ log_notice("%s(): Using root %s; Secure mode %s; "
+ "Running as uid=%d, gid=%d", __func__, context->root,
+ context->secure? "enabled" : "disabled", getuid(), getgid());
+
+ return (0);
+} /* obexapp_server_set_final_root */
+
+/*
  * Process OBEX_EV_REQHINT event
  */
 
@@ -565,6 +679,15 @@
  }
  }
 
+ if (chmod(context->temp, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) < 0) {
+ log_err("%s(): Could not chmod(%s). %s (%d)",
+ __func__, context->temp,
+ strerror(errno), errno);
+
+ codes = obexapp_util_errno2response(errno);
+ goto done;
+ }
+
  if (rename(context->temp, context->file) < 0) {
  log_err("%s(): Could not rename(%s, %s). %s (%d)",
  __func__, context->temp,
Index: transport.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/transport.c,v
retrieving revision 1.13
diff -u -r1.13 transport.c
--- transport.c 21 May 2007 15:55:35 -0000 1.13
+++ transport.c 14 Apr 2009 21:26:02 -0000
@@ -1,7 +1,7 @@
 /*
  * transport.c
  *
- * Copyright (c) 2001 Maksim Yevmenkin <m_evmenkin@...>
+ * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@...>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -280,6 +280,9 @@
  return (-1);
  }
 
+ memcpy(&context->raddr, &addr.rfcomm_bdaddr,
+ sizeof(context->raddr));
+
  return (1);
  }
 
Index: util.c
===================================================================
RCS file: /usr/local/cvs/ports/obexapp/util.c,v
retrieving revision 1.14
diff -u -r1.14 util.c
--- util.c 10 Apr 2009 17:26:03 -0000 1.14
+++ util.c 14 Apr 2009 21:26:08 -0000
@@ -1,7 +1,7 @@
 /*
  * util.c
  *
- * Copyright (c) 2002 Maksim Yevmenkin <m_evmenkin@...>
+ * Copyright (c) 2002-2009 Maksim Yevmenkin <m_evmenkin@...>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -425,9 +425,7 @@
  * string, so always pass a copy.
  */
 
- strncpy(n, name, sizeof(n));
- n[sizeof(n) - 1] = '\0';
-
+ strlcpy(n, name, sizeof(n));
  snprintf(temp, temp_size, "%s/XXXXXXXX", dirname(n));
 
  return (mkstemp(temp));

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Maksim Yevmenkin написав(ла):
> hopefully the latest patch will work for everyone.
>  
Little nits this time...

1. Even when the service is not running as root to begin with (and thus
chroot is impossible), a user owning multiple devices may wish to have
separate directories for each one. Yet, the new -R switch, as proposed,
requires successful chroot into a matching entry... It does not need to.
How about:

    + case 'R': /* virtualize root for each device */
    + context.vroot = 1;
    + if (getuid() == 0)
    + context.secure = 1;
    + break;
    +

chdir should be used instead of chroot in this case (-R was given, and a
matching entry is found, but we aren't running as root).

2. When going through the list of possible subdirectories-candidates,
hardcoding the number 3 is a bit dangerous. Using either

    sizeof(root)/sizeof(root[0])

or simply going, until hitting NULL:

    char const *root[] = { NULL, NULL, NULL, NULL }, **r;
    ...
    foreach (r -> root; *r; r++) {

        log_debug("%s(): Checking for %s/%s subdirectory",
            __func__, context->root, *r);
        ...

would be a bit safer going forward -- what if some other parameter (such
as an environment variable) may some day be added to the list of
considerations?

3. After starting up, with the -R (or the -r) option, should/does not
the daemon chdir into the specified top-level directory? And if so,
there is no need to assemble the context->root with strlcat -- just
perform chdir into the relative root[n] (or *r in my example). The
chroot can then happen to ".". After chdir-ing, you can populate the
actual contet->root with getcwd(context->root, PATH_MAX) -- a faster
equivalent to using realpath(3).

This is not material, but the fewer cases, where a hard-coded PATH_MAX
is used instead of the POSIX-approved pathconf(2), the better...

Yours,

    -mi

P.S. Thank you very much for keeping the wallabies in the manual's
examples. Better creatures are not to be found, and it is certainly
nicer to use them instead of the ubiquitous "foo" and "bar".
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mike Meyer-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, 14 Apr 2009 09:34:43 -0700
Maksim Yevmenkin <maksim.yevmenkin@...> wrote:

> > Maksim Yevmenkin написав(ла):
> > because all of the bluetooth users would have to be listed in obex'
> > group and so there can be no more than 20 of them (I think, that's the
> > limit on a group size).

Just so this doesn't wind up being quoted as accurate:

There are no limits on how many people can be in a group. There is a
limit on how many groups a person can be in (or was; I haven't
verified that this hasn't been changed recently).

BSD was used at UC Berkeley (the B in BSD) on machines with thousands
of users, and groups with hundreds of members. We had to db'ify the
password file, but the groups code worked just fine.

         <mike
--
Mike Meyer <mwm@...> http://www.mired.org/consulting.html
Independent Network/Unix/Perforce consultant, email for more information.

O< ascii ribbon campaign - stop html mail - www.asciiribbon.org
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Maksim Yevmenkin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/4/14 Mikhail T. <mi+thun@...>:

> Maksim Yevmenkin написав(ла):
>> hopefully the latest patch will work for everyone.
>>
> Little nits this time...
>
> 1. Even when the service is not running as root to begin with (and thus
> chroot is impossible), a user owning multiple devices may wish to have
> separate directories for each one. Yet, the new -R switch, as proposed,
> requires successful chroot into a matching entry... It does not need to.
> How about:
>
>    +           case 'R': /* virtualize root for each device */
>    +                   context.vroot = 1;
>    +                   if (getuid() == 0)
>    +                           context.secure = 1;
>    +                   break;
>    +
>
> chdir should be used instead of chroot in this case (-R was given, and a
> matching entry is found, but we aren't running as root).

well, a couple of things. for now, we always have to start obexapp as
root because it needs to talk to sdpd(8) to register services. sdpd(8)
is checking credentials (passed via unix sockets) and makes sure that
the process, that is trying to register the service, has uid of 'root'
user. so, strictly speaking this change is a no-op because getuid()
will always be 0 or else obexapp will not start in server mode.

also, i'd _really_ like to keep clients "jailed" under their virtual
root folders. at least for now. as far as keeping and sharing files
under the same root folder, i just thought of a way to "break" the
latest patch: set up symlink that points to '.' under default root
folder. obviously chdir() and chroot() conditions will be satisfied
and you get your files dumped in the same directory.

> 2. When going through the list of possible subdirectories-candidates,
> hardcoding the number 3 is a bit dangerous. Using either
>
>    sizeof(root)/sizeof(root[0])
>
> or simply going, until hitting NULL:
>
>    char const *root[] = { NULL, NULL, NULL, NULL }, **r;
>    ...
>    foreach (r -> root; *r; r++) {
>
>        log_debug("%s(): Checking for %s/%s subdirectory",
>            __func__, context->root, *r);
>        ...
>
> would be a bit safer going forward -- what if some other parameter (such
> as an environment variable) may some day be added to the list of
> considerations?

that's fine. i will fix it.

> 3. After starting up, with the -R (or the -r) option, should/does not
> the daemon chdir into the specified top-level directory? And if so,
> there is no need to assemble the context->root with strlcat -- just
> perform chdir into the relative root[n] (or *r in my example). The
> chroot can then happen to ".". After chdir-ing, you can populate the
> actual contet->root with getcwd(context->root, PATH_MAX) -- a faster
> equivalent to using realpath(3).

it does, chdir(), i.e. obexapp_server_set_initial_root() does it.
strlcat() is not that expensive, imo. it can be changed, i guess.

> This is not material, but the fewer cases, where a hard-coded PATH_MAX
> is used instead of the POSIX-approved pathconf(2), the better...

PATH_MAX comes from sys/syslimits.h, so, i thought it would be ok to
use. another alternative was MAXPATHLEN which was the same.

thanks,
max
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Maksim Yevmenkin написав(ла):

> 2009/4/14 Mikhail T. <mi+thun@...>:
>  
>> Maksim Yevmenkin написав(ла):
>>    
>>> hopefully the latest patch will work for everyone.
>>>      
>> Little nits this time...
>>
>> 1. Even when the service is not running as root to begin with (and thus
>> chroot is impossible), a user owning multiple devices may wish to have
>> separate directories for each one. Yet, the new -R switch, as proposed,
>> requires successful chroot into a matching entry... It does not need to.
>> How about:
>>
>>    +           case 'R': /* virtualize root for each device */
>>    +                   context.vroot = 1;
>>    +                   if (getuid() == 0)
>>    +                           context.secure = 1;
>>    +                   break;
>>    +
>>
>> chdir should be used instead of chroot in this case (-R was given, and a
>> matching entry is found, but we aren't running as root).
>>    
>
> well, a couple of things. for now, we always have to start obexapp as
> root because it needs to talk to sdpd(8) to register services. sdpd(8)
> is checking credentials (passed via unix sockets) and makes sure that
> the process, that is trying to register the service, has uid of 'root'
> user. so, strictly speaking this change is a no-op because getuid()
> will always be 0 or else obexapp will not start in server mode.
>  
Oh, that must be why I couldn't start obexapp as myself before... So,
all of those getuid() calls are no-ops too? Either they need to be
eliminated, or, if other ways of authenticating to sdp are in the works,
ability to chroot should not be a requirement.
> also, i'd _really_ like to keep clients "jailed" under their virtual
> root folders. at least for now. as far as keeping and sharing files
> under the same root folder, i just thought of a way to "break" the
> latest patch: set up symlink that points to '.' under default root
> folder. obviously chdir() and chroot() conditions will be satisfied
> and you get your files dumped in the same directory.
>  
Right, of course. The symlinks can point to . or to some external
/home/dropoff -- same thing.

>
>> 3. After starting up, with the -R (or the -r) option, should/does not
>> the daemon chdir into the specified top-level directory? And if so,
>> there is no need to assemble the context->root with strlcat -- just
>> perform chdir into the relative root[n] (or *r in my example). The
>> chroot can then happen to ".". After chdir-ing, you can populate the
>> actual contet->root with getcwd(context->root, PATH_MAX) -- a faster
>> equivalent to using realpath(3).
>>    
>
> it does, chdir(), i.e. obexapp_server_set_initial_root() does it.
> strlcat() is not that expensive, imo. it can be changed, i guess.
>  
It is not expensive, but not needed either :) After a chdir succeeds,
the chroot can go simply into "."
>> This is not material, but the fewer cases, where a hard-coded PATH_MAX
>> is used instead of the POSIX-approved pathconf(2), the better...
>>    
> PATH_MAX comes from sys/syslimits.h, so, i thought it would be ok to
> use. another alternative was MAXPATHLEN which was the same.
>  
The gist of the PATH_MAX/MAXPATHLEN vs. pathconf() controversy is that
the latter may change after the program is compiled. Thus relying on ANY
compile-time buffer-length as being "long enough" is potentially
dangerous (and almost always wasteful).

Logging the actual directory (as can be determined by getwd(NULL) after
chdir-ing, but before chroot-ing), rather than the name of the symlink
can be seen as beneficial too.

Yours,

    -mi

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

group-related limits (Re: RFC: obexapp - virtual root folder for each device)

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Mike Meyer написав(ла):

> On Tue, 14 Apr 2009 09:34:43 -0700
> Maksim Yevmenkin <maksim.yevmenkin@...> wrote:
>
>  
>>> Maksim Yevmenkin написав(ла):
>>> because all of the bluetooth users would have to be listed in obex'
>>> group and so there can be no more than 20 of them (I think, that's the
>>> limit on a group size).
>>>      
>
> Just so this doesn't wind up being quoted as accurate:
>
> There are no limits on how many people can be in a group. There is a
> limit on how many groups a person can be in (or was; I haven't
> verified that this hasn't been changed recently).
Thanks for the correction, Mike. I had only a vague memory of there
being some limits related to groups -- from years ago :-)

But still, if a person can only participate in so many groups, forcing
participation in yet another one for common, non-administrative
functionality should be avoided...

Fortunately, we seem to have just agreed on a more straightforward way
anyway. Yours,

    -mi

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: group-related limits (Re: RFC: obexapp - virtual root folder for each device)

by Iain Hibbert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Tue, 14 Apr 2009, Mikhail T. wrote:

> Mike Meyer ÿÿÿÿÿÿÿÿÿÿÿÿÿÿ(ÿÿÿÿ):
> > There are no limits on how many people can be in a group. There is a
> > limit on how many groups a person can be in (or was; I haven't
> > verified that this hasn't been changed recently).
>
> Thanks for the correction, Mike. I had only a vague memory of there
> being some limits related to groups -- from years ago :-)

I don't know about FreeBSD but on NetBSD there is AFAIK no limit to the
number of groups that a user can be in. The "20 groups" limit comes from
NFS which used a fixed array in its specifications (and so is a problem on
any operating system)

iain
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Mikhail T.-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Maksim, I just tried building the most recent obexapp from port (1.4.11)
and was surprised to find out, that the feature, which we spent so much
effort rehashing back in April, is still not there... What's holding it
up? Thanks! Yours,

    -mi

_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."

Re: RFC: obexapp - virtual root folder for each device

by Maksim Yevmenkin-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/7/13 Mikhail T. <mi+thun@...>:
> Maksim, I just tried building the most recent obexapp from port (1.4.11)
> and was surprised to find out, that the feature, which we spent so much
> effort rehashing back in April, is still not there... What's holding it
> up? Thanks! Yours,

thanks for the ping. yes, terribly sorry, i'm completely swamped with
$realjob :( i'll try to get to it as soon as i can.

max
_______________________________________________
freebsd-bluetooth@... mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-bluetooth
To unsubscribe, send any mail to "freebsd-bluetooth-unsubscribe@..."