summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bluetooth
diff options
context:
space:
mode:
authoremax <emax@FreeBSD.org>2005-12-06 17:56:36 +0000
committeremax <emax@FreeBSD.org>2005-12-06 17:56:36 +0000
commit33f5a902c54a3c48d2ad668c3399f8b5d3cbe1aa (patch)
treefb49b5260c303252ffc020521385ecddc194bd1e /usr.sbin/bluetooth
parentad3630f76e09394ffde1515f25e05b7be7f30eff (diff)
downloadFreeBSD-src-33f5a902c54a3c48d2ad668c3399f8b5d3cbe1aa.zip
FreeBSD-src-33f5a902c54a3c48d2ad668c3399f8b5d3cbe1aa.tar.gz
Teach sdpd(8) to check peer's credentials before accepting request to
register, remove or change services in the local database. For now only accept the request if the peer has effective user ID the same as 'root' user ID. MFC after: 1 week
Diffstat (limited to 'usr.sbin/bluetooth')
-rw-r--r--usr.sbin/bluetooth/sdpd/scr.c3
-rw-r--r--usr.sbin/bluetooth/sdpd/sdpd.812
-rw-r--r--usr.sbin/bluetooth/sdpd/server.c40
-rw-r--r--usr.sbin/bluetooth/sdpd/server.h3
-rw-r--r--usr.sbin/bluetooth/sdpd/srr.c3
-rw-r--r--usr.sbin/bluetooth/sdpd/sur.c3
6 files changed, 55 insertions, 9 deletions
diff --git a/usr.sbin/bluetooth/sdpd/scr.c b/usr.sbin/bluetooth/sdpd/scr.c
index f6f482d..d0c9ec5 100644
--- a/usr.sbin/bluetooth/sdpd/scr.c
+++ b/usr.sbin/bluetooth/sdpd/scr.c
@@ -58,7 +58,8 @@ server_prepare_service_change_response(server_p srv, int32_t fd)
* value32 - handle 4 bytes
*/
- if (!srv->fdidx[fd].control || req_end - req < 4)
+ if (!srv->fdidx[fd].control ||
+ !srv->fdidx[fd].priv || req_end - req < 4)
return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
/* Get handle */
diff --git a/usr.sbin/bluetooth/sdpd/sdpd.8 b/usr.sbin/bluetooth/sdpd/sdpd.8
index 571e908..0844e30 100644
--- a/usr.sbin/bluetooth/sdpd/sdpd.8
+++ b/usr.sbin/bluetooth/sdpd/sdpd.8
@@ -110,10 +110,14 @@ possible to specify which services should be
to which Bluetooth device.
Such assignment should be done at service registration time.
.Pp
-Access rights on the control socket define which application can register,
-remove or change the service.
-The application must be able to write to and read from the control socket
-in order to perform any query to the Service Database via control socket.
+Requests to register, remove or change service can only be made via the
+control socket.
+The
+.Nm
+daemon will check peer's credentials and will only accept the request if
+the application has the same effective user ID as the
+.Dq Li root
+user ID.
.Pp
The
.Nm
diff --git a/usr.sbin/bluetooth/sdpd/server.c b/usr.sbin/bluetooth/sdpd/server.c
index 14b2041..d07b549 100644
--- a/usr.sbin/bluetooth/sdpd/server.c
+++ b/usr.sbin/bluetooth/sdpd/server.c
@@ -29,14 +29,18 @@
* $FreeBSD$
*/
+#include <sys/param.h>
#include <sys/select.h>
+#include <sys/stat.h>
#include <sys/queue.h>
+#include <sys/ucred.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <assert.h>
#include <bluetooth.h>
#include <errno.h>
+#include <pwd.h>
#include <sdp.h>
#include <stdio.h>
#include <stdlib.h>
@@ -96,6 +100,13 @@ server_init(server_p srv, char const *control)
return (-1);
}
+ if (chmod(control, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) < 0) {
+ log_crit("Could not change permissions on control socket. " \
+ "%s (%d)", strerror(errno), errno);
+ close(unsock);
+ return (-1);
+ }
+
if (listen(unsock, 10) < 0) {
log_crit("Could not listen on control socket. %s (%d)",
strerror(errno), errno);
@@ -185,6 +196,7 @@ server_init(server_p srv, char const *control)
srv->fdidx[unsock].valid = 1;
srv->fdidx[unsock].server = 1;
srv->fdidx[unsock].control = 1;
+ srv->fdidx[unsock].priv = 0;
srv->fdidx[unsock].rsp_cs = 0;
srv->fdidx[unsock].rsp_size = 0;
srv->fdidx[unsock].rsp_limit = 0;
@@ -195,6 +207,7 @@ server_init(server_p srv, char const *control)
srv->fdidx[l2sock].valid = 1;
srv->fdidx[l2sock].server = 1;
srv->fdidx[l2sock].control = 0;
+ srv->fdidx[l2sock].priv = 0;
srv->fdidx[l2sock].rsp_cs = 0;
srv->fdidx[l2sock].rsp_size = 0;
srv->fdidx[l2sock].rsp_limit = 0;
@@ -276,7 +289,7 @@ static void
server_accept_client(server_p srv, int32_t fd)
{
uint8_t *rsp = NULL;
- int32_t cfd, size;
+ int32_t cfd, size, priv;
uint16_t omtu;
do {
@@ -293,6 +306,8 @@ server_accept_client(server_p srv, int32_t fd)
assert(!FD_ISSET(cfd, &srv->fdset));
assert(!srv->fdidx[cfd].valid);
+ priv = 0;
+
if (!srv->fdidx[fd].control) {
/* Get local BD_ADDR */
size = sizeof(srv->req_sa);
@@ -326,6 +341,28 @@ server_accept_client(server_p srv, int32_t fd)
return;
}
} else {
+ struct xucred cr;
+ struct passwd *pw;
+
+ /* Get peer's credentials */
+ memset(&cr, 0, sizeof(cr));
+ size = sizeof(cr);
+
+ if (getsockopt(cfd, 0, LOCAL_PEERCRED, &cr, &size) < 0) {
+ log_err("Could not get peer's credentials. %s (%d)",
+ strerror(errno), errno);
+ close(cfd);
+ return;
+ }
+
+ /* Check credentials */
+ pw = getpwuid(cr.cr_uid);
+ if (pw != NULL)
+ priv = (strcmp(pw->pw_name, "root") == 0);
+ else
+ log_warning("Could not verify credentials for uid %d",
+ cr.cr_uid);
+
memcpy(&srv->req_sa.l2cap_bdaddr, NG_HCI_BDADDR_ANY,
sizeof(srv->req_sa.l2cap_bdaddr));
@@ -351,6 +388,7 @@ server_accept_client(server_p srv, int32_t fd)
srv->fdidx[cfd].valid = 1;
srv->fdidx[cfd].server = 0;
srv->fdidx[cfd].control = srv->fdidx[fd].control;
+ srv->fdidx[cfd].priv = priv;
srv->fdidx[cfd].rsp_cs = 0;
srv->fdidx[cfd].rsp_size = 0;
srv->fdidx[cfd].rsp_limit = 0;
diff --git a/usr.sbin/bluetooth/sdpd/server.h b/usr.sbin/bluetooth/sdpd/server.h
index 6f8f088..d7ef55e 100644
--- a/usr.sbin/bluetooth/sdpd/server.h
+++ b/usr.sbin/bluetooth/sdpd/server.h
@@ -41,7 +41,8 @@ struct fd_idx
unsigned valid : 1; /* descriptor is valid */
unsigned server : 1; /* descriptor is listening */
unsigned control : 1; /* descriptor is a control socket */
- unsigned reserved : 2;
+ unsigned priv : 1; /* descriptor is privileged */
+ unsigned reserved : 1;
unsigned rsp_cs : 11; /* response continuation state */
uint16_t rsp_size; /* response size */
uint16_t rsp_limit; /* response limit */
diff --git a/usr.sbin/bluetooth/sdpd/srr.c b/usr.sbin/bluetooth/sdpd/srr.c
index a1f3ded..fd636d5 100644
--- a/usr.sbin/bluetooth/sdpd/srr.c
+++ b/usr.sbin/bluetooth/sdpd/srr.c
@@ -65,7 +65,8 @@ server_prepare_service_register_response(server_p srv, int32_t fd)
* bdaddr - BD_ADDR 6 bytes
*/
- if (!srv->fdidx[fd].control || req_end - req < 8)
+ if (!srv->fdidx[fd].control ||
+ !srv->fdidx[fd].priv || req_end - req < 8)
return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
/* Get ServiceClass UUID */
diff --git a/usr.sbin/bluetooth/sdpd/sur.c b/usr.sbin/bluetooth/sdpd/sur.c
index 6d7f778..143eaf3 100644
--- a/usr.sbin/bluetooth/sdpd/sur.c
+++ b/usr.sbin/bluetooth/sdpd/sur.c
@@ -58,7 +58,8 @@ server_prepare_service_unregister_response(server_p srv, int32_t fd)
* value32 - uuid 4 bytes
*/
- if (!srv->fdidx[fd].control || req_end - req < 4)
+ if (!srv->fdidx[fd].control ||
+ !srv->fdidx[fd].priv || req_end - req < 4)
return (SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX);
/* Get handle */
OpenPOWER on IntegriCloud