|
View:
New views
20 Messages
—
Rating Filter:
Alert me
|
|
|
RFC: obexapp - virtual root folder for each devicedear 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 deviceMaksim 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. > 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 device2009/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 deviceMaksim 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 deviceOn 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 device2009/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 deviceOn 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 deviceMaksim 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? > 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). > 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 deviceIain 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 device2009/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 deviceMaksim 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 ... > -- 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'). > 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 device2009/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 deviceMaksim 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 deviceOn 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 device2009/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 deviceMaksim 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. > 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. > 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)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). 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)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 deviceMaksim, 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 device2009/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@..." |
| Free embeddable forum powered by Nabble | Forum Help |