PERFORCE change 164441 for review
Jonathan Anderson
jona at FreeBSD.org
Mon Jun 15 17:56:17 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=164441
Change 164441 by jona at jona-trustedbsd-belle-vm on 2009/06/15 17:55:46
Sandbox/angel RPC to request single files and powerboxes
Affected files ...
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/Makefile#5 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/cap.c#3 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/fdtest.c#4 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/powerbox.c#3 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/powerbox.h#3 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.c#8 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.h#7 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/server.c#4 edit
.. //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/test_client.c#4 edit
Differences ...
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/Makefile#5 (text+ko) ====
@@ -1,25 +1,22 @@
-CFLAGS=-g -ggdb --std=c99 -Wall -Werror #-pedantic-errors
+VERSION=dev-pre1
+CFLAGS=-g -ggdb --std=c99 -Wall -Werror -pedantic-errors -DVERSION='"${VERSION}"'
+LDFLAGS=-L/usr/local/lib -lefence
-BIN=user_angel test_client fdtest
-AGENT_OBJ = user_angel.o server.o cap.o protocol.o fdcomm.o powerbox.o
-CLIENT_OBJ = test_client.o protocol.o fdcomm.o
+BIN=user_angel test_client
+AGENT_OBJ = user_angel.o server.o cap.o protocol.o powerbox.o
+CLIENT_OBJ = test_client.o protocol.o
all: ${BIN}
user_angel: ${AGENT_OBJ}
- ${CC} -o $@ ${AGENT_OBJ}
+ ${CC} ${LDFLAGS} -o $@ ${AGENT_OBJ}
test_client: ${CLIENT_OBJ}
- ${CC} -o $@ ${CLIENT_OBJ}
+ ${CC} ${LDFLAGS} -o $@ ${CLIENT_OBJ}
-fdtest: fdtest.o fdcomm.o protocol.o
- ${CC} -o $@ fdtest.o fdcomm.o protocol.o
-
cap.o: cap.c cap.h
-fdcomm.o: fdcomm.c fdcomm.h
-fdtest.o: fdtest.c protocol.h
powerbox.o: powerbox.c powerbox.h
protocol.o: protocol.c protocol.h powerbox.h
server.o: server.c protocol.h server.h
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/cap.c#3 (text+ko) ====
@@ -47,6 +47,7 @@
int cap = cap_new(fd, rights);
if(cap < 0) err(EX_SOFTWARE, "failed to create new capability");
+ close(fd);
return cap;
}
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/fdtest.c#4 (text+ko) ====
@@ -85,7 +85,7 @@
struct cap_wire_datum *d = cap_marshall_string(message, strlen(message));
- if(cap_send_fd(sock, "message and FDs", d, fds, fdlen) < 0)
+ if(cap_send_fd(sock, d, fds, fdlen) < 0)
err(EX_IOERR, "Error sending data/FD");
free(d);
@@ -94,9 +94,8 @@
int fd_array[10];
fdlen = 10;
- char *name;
- if(cap_recv_fd(sock, &name, &d, fd_array, &fdlen) < 0)
- err(EX_IOERR, "Error receiving data/FD");
+ d = cap_recv_fds(sock, fd_array, &fdlen);
+ if(!d) err(EX_IOERR, "Error receiving data/FD");
printf("Received datum:\n");
printf(" type: %i\n", d->type);
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/powerbox.c#3 (text+ko) ====
@@ -34,12 +34,16 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <fcntl.h>
#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#include "powerbox.h"
-int capbox_display(struct capbox_options *options)
+int capbox_display(struct capbox_options *options, int fds[], char *names[],
+ int *len)
{
printf("capbox_display()\n");
printf(" options:\n");
@@ -73,8 +77,26 @@
if(options->filterlen > 0) printf("%s\n", options->filter);
else printf("<none>\n");
- fprintf(stderr, "powerbox not implemented\n");
+ fprintf(stderr, "powerbox not implemented, faking it\n");
+
+ if(*len > 0)
+ {
+ names[0] = (char*) malloc(32);
+ strcpy(names[0], "/etc/hosts");
+
+ fds[0] = open("/etc/hosts", O_RDONLY);
+ }
+
+ if(*len > 1)
+ {
+ names[1] = (char*) malloc(32);
+ strcpy(names[1], "/etc/nsswitch.conf");
+
+ fds[1] = open("/etc/nsswitch.conf", O_RDONLY);
+ }
+
+ if(*len > 2) *len = 2;
- return -1;
+ return 0;
}
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/powerbox.h#3 (text+ko) ====
@@ -48,11 +48,11 @@
enum capbox_op_t operation; /* operation to perform */
char* window_title; /* set by user_angel, not sandbox */
int parent_window; /* X11 window to attach to (or 0) */
- char* start_path; /* path to start in (or NULL) */
+ const char* start_path; /* path to start in (or NULL) */
int pathlen; /* length of start path */
int start_fd; /* FD to start in (or -1) */
int mult; /* allow multiple selection */
- char* filter; /* filter expression (or NULL) */
+ const char* filter; /* filter expression (or NULL) */
int filterlen; /* length of filter expression */
};
@@ -60,7 +60,8 @@
/**
* Open a powerbox.
*
- * @return a capability file descriptor or -1
+ * @return 0 on success
*/
-int capbox_display(struct capbox_options *options);
+int capbox_display(struct capbox_options *options, int fds[], char *names[],
+ int *len);
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.c#8 (text+ko) ====
@@ -45,85 +45,305 @@
-struct cap_wire_datum* cap_marshall_int(int32_t value)
+
+
+void print_datum(const struct cap_wire_datum *d)
+{
+ printf("Datum @ 0x%8x:\n", (unsigned int) d);
+ printf(" type: %i\n", d->type);
+ printf(" length: %i\n", d->length);
+ printf(" data: ");
+ for(int j = 0; j < d->length; j++)
+ {
+ unsigned char *address = ((unsigned char*) d);
+ address += sizeof(struct cap_wire_datum) + j;
+
+ printf("%02x ", *address);
+ }
+ printf("\n");
+}
+
+
+
+
+typedef struct cap_wire_datum wire_datum;
+
+
+char errmsg[256];
+const char* cap_error(void) { return errmsg; }
+
+
+wire_datum* cap_marshall_int(int32_t value)
{
- int size = sizeof(struct cap_wire_datum) + sizeof(int32_t);
- struct cap_wire_datum *d = (struct cap_wire_datum*) malloc(size);
+ int size = sizeof(wire_datum) + sizeof(int32_t);
+ wire_datum *d = (wire_datum*) malloc(size);
d->type = INTEGER;
d->length = sizeof(int32_t);
- ((int32_t*) d + sizeof(struct cap_wire_datum))[0] = value;
+
+ void *address = ((char*) d) + sizeof(wire_datum);
+ ((int32_t*) address)[0] = value;
return d;
}
-int cap_unmarshall_int(struct cap_wire_datum *datum, int32_t *value)
+int cap_unmarshall_int(const wire_datum *datum, int32_t *value)
{
+ if(datum == NULL)
+ {
+ sprintf(errmsg, "Datum is NULL");
+ return -1;
+ }
+
+ if(!(datum->type & INTEGER))
+ {
+ sprintf(errmsg, "Datum's type is %i, not INTEGER (%i)",
+ datum->type, INTEGER);
+ return -1;
+ }
+
if(datum->length != 4)
{
- fprintf(stderr, "Error unmarshalling int: should be 4B long, not %i\n",
- datum->length);
+ sprintf(errmsg, "An 32-bit integer should be 4B long, not %i",
+ datum->length);
return -1;
}
- memcpy(value, ((void*) datum) + sizeof(struct cap_wire_datum), 4);
+ memcpy(value, ((char*) datum) + sizeof(wire_datum), 4);
return datum->length;
}
-struct cap_wire_datum* cap_marshall_string(char *value, int len)
+wire_datum* cap_marshall_string(const char *value, int len)
{
- int size = sizeof(struct cap_wire_datum) + len;
- struct cap_wire_datum *d = (struct cap_wire_datum*) malloc(size);
+ int size = sizeof(wire_datum) + len;
+ wire_datum *d = (wire_datum*) malloc(size);
d->type = STRING;
d->length = len;
- memcpy(((char*) d) + sizeof(struct cap_wire_datum), value, len);
+ memcpy(((char*) d) + sizeof(wire_datum), value, len);
return d;
}
-int cap_unmarshall_string(struct cap_wire_datum *datum, char *value, int *len)
+int cap_unmarshall_string(const wire_datum *datum, char *value, int *len)
{
+ if(datum == NULL)
+ {
+ sprintf(errmsg, "NULL datum");
+ return -1;
+ }
+ else if(datum->type != STRING)
+ {
+ sprintf(errmsg, "Datum's type is %i, not STRING (%i)",
+ datum->type, STRING);
+ }
+ else if(datum->length < 0)
+ {
+ sprintf(errmsg, "Datum length should be positive, not %i",
+ datum->length);
+ return -1;
+ }
+ else if(datum->length >= *len)
+ {
+ sprintf(errmsg, "String in datum is too long (%iB) to fit in buffer (%iB)",
+ datum->length, *len);
+ return -1;
+ }
+
*len = datum->length;
- if(datum->length < 0)
+ memcpy(value, ((char*) datum) + sizeof(wire_datum), datum->length);
+ value[*len] = '\0';
+
+ return datum->length;
+}
+
+
+wire_datum* cap_marshall_capbox(const struct capbox_options *options)
+{
+ wire_datum *data[6];
+ data[0] = cap_marshall_int(options->ui);
+ data[1] = cap_marshall_int(options->operation);
+ data[2] = cap_marshall_int(options->parent_window);
+ data[3] = cap_marshall_string(options->start_path, options->pathlen);
+ data[4] = cap_marshall_int(options->mult);
+ data[5] = cap_marshall_string(options->filter, options->filterlen);
+
+ int total_size = 0;
+ for(int i = 0; i < 6; i++)
+ if(data[i] == NULL)
+ {
+ sprintf(errmsg, "Capbox datum %i is NULL", i);
+ return NULL;
+ }
+ else total_size += (sizeof(wire_datum) + data[i]->length);
+
+ wire_datum *d = (wire_datum*) malloc(sizeof(wire_datum) + total_size);
+ d->type = CAPBOX_OPTIONS;
+ d->length = total_size;
+
+ char *buffer = ((char*) d) + sizeof(wire_datum);
+ char *head = buffer;
+ for(int i = 0; i < 6; i++)
+ {
+ memcpy(head, data[i], sizeof(wire_datum) + data[i]->length);
+ head += sizeof(wire_datum) + data[i]->length;
+
+ free(data[i]);
+ }
+
+ return d;
+}
+
+
+int cap_unmarshall_capbox(const wire_datum *datum, struct capbox_options *options)
+{
+ if(datum == NULL)
+ {
+ sprintf(errmsg, "NULL datum");
+ return -1;
+ }
+ else if(datum->type != CAPBOX_OPTIONS)
+ {
+ sprintf(errmsg, "Datum's type is %i, not CAPBOX_OPTIONS (%i)",
+ datum->type, CAPBOX_OPTIONS);
+ }
+ else if(datum->length < 0)
{
- fprintf(stderr, "Error unmarshalling int: should be positive, not %i\n",
+ sprintf(errmsg, "Datum length should be positive, not %i",
datum->length);
return -1;
}
- memcpy(value, ((void*) datum) + sizeof(struct cap_wire_datum), datum->length);
- return datum->length;
+ int32_t tmp_int;
+ wire_datum *d = (wire_datum*) (((char*) datum) + sizeof(wire_datum));
+
+ if(cap_unmarshall_int(d, &tmp_int) < 0)
+ {
+ char error[128];
+ sprintf(error, "Error unmarshalling UI type: %s", cap_error());
+ strcpy(errmsg, error);
+ return -1;
+ }
+ options->ui = tmp_int;
+ d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+ if(cap_unmarshall_int(d, &tmp_int) < 0)
+ {
+ char error[128];
+ sprintf(error, "Error unmarshalling operation: %s", cap_error());
+ strcpy(errmsg, error);
+ return -1;
+ }
+ options->operation = tmp_int;
+ d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+
+ // window title is handled elsewhere
+
+
+ if(cap_unmarshall_int(d, &tmp_int) < 0)
+ {
+ char error[128];
+ sprintf(error, "Error unmarshalling parent: %s", cap_error());
+ strcpy(errmsg, error);
+ return -1;
+ }
+ options->parent_window = tmp_int;
+ d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+ options->pathlen = d->length + 1;
+ options->start_path = (char*) malloc(options->pathlen);
+ if(cap_unmarshall_string(d, (char*) options->start_path, &options->pathlen) < 0)
+ {
+ char error[128];
+ sprintf(error, "Error unmarshalling path: %s", cap_error());
+ strcpy(errmsg, error);
+ return -1;
+ }
+ d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+
+ // don't do anything about the start_fd file descriptor;
+ // that's handled at the recvmsg() level
+
+
+ if(cap_unmarshall_int(d, &tmp_int) < 0)
+ {
+ char error[128];
+ sprintf(error, "Error unmarshalling 'mult': %s", cap_error());
+ strcpy(errmsg, error);
+ return -1;
+ }
+ options->mult = tmp_int;
+ d = (wire_datum*) (((char*) d) + sizeof(wire_datum) + d->length);
+
+ options->filterlen = d->length + 1;
+ options->filter = (char*) malloc(options->filterlen);
+ if(cap_unmarshall_string(d, (char*) options->filter, &options->filterlen) < 0)
+ {
+ char error[128];
+ sprintf(error, "Error unmarshalling filter: %s", cap_error());
+ strcpy(errmsg, error);
+ return -1;
+ }
+
+
+ return sizeof(wire_datum) + datum->length;
+}
+
+
+
+int cap_send_message(int sock, wire_datum *data[], int len)
+{
+ int total_bytes = 0;
+ for(int i = 0; i < len; i++)
+ {
+ int bytes = cap_send(sock, data[i]);
+
+ if(bytes < 0) return bytes;
+ else total_bytes += bytes;
+ }
+
+ return total_bytes;
+}
+
+
+
+int cap_send(int sock, wire_datum *datum)
+{
+ return cap_send_fd(sock, datum, NULL, 0);
}
-/*
-int cap_send(int sock, struct cap_wire_datum* datum);
-*/
-int cap_send_fd(int sock, const char *name, struct cap_wire_datum *d,
+int cap_send_fd(int sock, wire_datum *d,
int32_t fd_array[], int32_t fdlen)
{
// the datum is the I/O vector
struct iovec iov;
iov.iov_base = d;
- iov.iov_len = sizeof(struct cap_wire_datum) + d->length;
+ iov.iov_len = sizeof(wire_datum) + d->length;
// ancilliary data (file descriptors)
- int cmsghdrlen = sizeof(struct cmsghdr) + fdlen * sizeof(int32_t);
- struct cmsghdr *anc_hdr = (struct cmsghdr*) malloc(cmsghdrlen);
- if(!anc_hdr) err(EX_OSERR, "Error creating ancilliary data header");
+ struct cmsghdr *anc_hdr = NULL;
+ if(fdlen > 0)
+ {
+ int cmsghdrlen = sizeof(struct cmsghdr) + fdlen * sizeof(int32_t);
+ anc_hdr = (struct cmsghdr*) malloc(cmsghdrlen);
+ if(!anc_hdr) err(EX_OSERR, "Error creating ancilliary data header");
+
+ anc_hdr->cmsg_len = cmsghdrlen;
+ anc_hdr->cmsg_level = SOL_SOCKET;
+ anc_hdr->cmsg_type = (fdlen ? SCM_RIGHTS : 0);
+ memcpy(((char*) anc_hdr) + sizeof(struct cmsghdr), fd_array,
+ fdlen * sizeof(int32_t));
+ }
- anc_hdr->cmsg_len = cmsghdrlen;
- anc_hdr->cmsg_level = SOL_SOCKET;
- anc_hdr->cmsg_type = SCM_RIGHTS;
- memcpy(((void*) anc_hdr) + sizeof(struct cmsghdr), fd_array,
- fdlen * sizeof(int32_t));
// sendmsg header
@@ -133,7 +353,7 @@
header.msg_iov = &iov;
header.msg_iovlen = 1;
header.msg_control = anc_hdr;
- header.msg_controllen = anc_hdr->cmsg_len;
+ header.msg_controllen = ((fdlen > 0) ? anc_hdr->cmsg_len : 0);
header.msg_flags = 0;
@@ -142,6 +362,7 @@
if(bytes_sent < 0)
{
perror("Error sending data and file descriptor(s)");
+ free(anc_hdr);
return -1;
}
@@ -151,37 +372,50 @@
}
+wire_datum* cap_recv(int sock)
+{
+ int fdlen = 0;
+ return cap_recv_fds(sock, NULL, &fdlen);
+}
+
-int cap_recv_fd(int sock, char **name, struct cap_wire_datum **d,
- int32_t *fd_array, int32_t *fdlen)
+wire_datum* cap_recv_fds(int sock, int32_t fd_array[], int32_t *fdlen)
{
// how much data is there to receive?
- struct cap_wire_datum peek;
- int bytes = recv(sock, &peek, sizeof(struct cap_wire_datum), MSG_PEEK);
- if(bytes < 0)
+ wire_datum peek;
+ int bytes = recv(sock, &peek, sizeof(wire_datum), MSG_PEEK);
+
+ if(bytes == 0)
+ {
+ sprintf(errmsg, "Socket closed: %s", strerror(errno));
+ return NULL;
+ }
+ else if(bytes < 0)
{
perror("Error peeking at socket");
- return -1;
+ return NULL;
}
- int to_receive = sizeof(struct cap_wire_datum) + peek.length;
+ int to_receive = sizeof(wire_datum) + peek.length;
// make room for it
- *d = (struct cap_wire_datum*) malloc(to_receive);
+ wire_datum *datum = (wire_datum*) malloc(to_receive);
struct iovec iov;
- iov.iov_base = *d;
+ iov.iov_base = datum;
iov.iov_len = to_receive;
// prepare to receive file descriptor(s)
- int size = sizeof(struct cmsghdr) + *fdlen;
+ int size = sizeof(struct cmsghdr) + *fdlen * sizeof(int32_t);
struct cmsghdr *anc_hdr = (struct cmsghdr*) malloc(size);
+ bzero(anc_hdr, size);
+
if(!anc_hdr) err(EX_OSERR, "Error creating ancilliary data header");
anc_hdr->cmsg_len = size;
anc_hdr->cmsg_level = SOL_SOCKET;
- anc_hdr->cmsg_type = SCM_RIGHTS;
- memset(anc_hdr + sizeof(struct cmsghdr), 0, *fdlen * sizeof(int32_t));
+ anc_hdr->cmsg_type = (*fdlen ? SCM_RIGHTS : 0);
+ bzero(anc_hdr + sizeof(struct cmsghdr), *fdlen * sizeof(int32_t));
// recvmsg() options
struct msghdr header;
@@ -198,12 +432,16 @@
if(bytes < 0)
{
perror("Error receiving message");
- return -1;
+ free(anc_hdr);
+ free(datum);
+ return NULL;
}
else if(bytes == 0)
{
fprintf(stderr, "Socket closed\n");
- return -1;
+ free(anc_hdr);
+ free(datum);
+ return NULL;
}
@@ -212,10 +450,12 @@
if(recv_fdlen < *fdlen) *fdlen = recv_fdlen;
- memcpy(fd_array, ((void*) anc_hdr) + sizeof(struct cmsghdr),
+ memcpy(fd_array, ((char*) anc_hdr) + sizeof(struct cmsghdr),
*fdlen * sizeof(int32_t));
- return 0;
+ free(anc_hdr);
+
+ return datum;
}
@@ -282,7 +522,7 @@
return total_bytes;
}
-
+/*
int cap_send_capbox_options(int client, struct capbox_options *options)
{
int bytes, total_bytes = 0;
@@ -302,11 +542,11 @@
bytes = cap_send_string(client, options->start_path, options->pathlen);
if(bytes <= 0) return bytes;
total_bytes += bytes;
-/* TODO: need to do a sendmsg with SCM_RIGHTS
+* TODO: need to do a sendmsg with SCM_RIGHTS
bytes = cap_send_int(client, options->start_fd);
if(bytes <= 0) return bytes;
total_bytes += bytes;
-*/
+*
bytes = cap_send_int(client, options->mult);
if(bytes <= 0) return bytes;
total_bytes += bytes;
@@ -340,11 +580,11 @@
total_bytes += bytes;
options->pathlen = bytes;
-/* TODO: need to do a sendmsg with SCM_RIGHTS
+* TODO: need to do a sendmsg with SCM_RIGHTS
bytes = cap_recv_int(client, &options->start_fd);
if(bytes <= 0) { perror("Error receiving path FD"); return bytes; }
total_bytes += bytes;
-*/
+*
options->start_fd = -1;
bytes = cap_recv_int(client, &options->mult);
@@ -359,4 +599,5 @@
return total_bytes;
}
+*/
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/protocol.h#7 (text+ko) ====
@@ -35,6 +35,22 @@
#include "powerbox.h"
+
+/** Requests that clients can make */
+enum capangel_req_t
+{
+ NO_OP = 0,
+ FD_FROM_PATH,
+ FD_POWERBOX
+};
+
+
+/** The last protocol error */
+const char* cap_error(void);
+
+
+
+/** Represents a single datum "on the wire" */
struct cap_wire_datum
{
uint32_t type;
@@ -51,49 +67,35 @@
uint32_t length;
- /* followed by data; */
+ /* immediately followed by actual data; */
};
-/** Requests that clients can make */
-enum capangel_req_t
-{
- FD_FROM_PATH,
- FD_POWERBOX
-};
-
-
-
/* Unmarshalling functions; calling programs should free the result */
struct cap_wire_datum* cap_marshall_int(int32_t value);
-struct cap_wire_datum* cap_marshall_string(char *value, int len);
+struct cap_wire_datum* cap_marshall_string(const char *value, int len);
+struct cap_wire_datum* cap_marshall_capbox(const struct capbox_options *options);
+
/* Unmarshalling functions; return the number of bytes unmarshalled (or -1) */
-int cap_unmarshall_int(struct cap_wire_datum *datum, int32_t *value);
-int cap_unmarshall_string(struct cap_wire_datum *datum, char* value, int *len);
+int cap_unmarshall_int(const struct cap_wire_datum *d, int32_t *value);
+int cap_unmarshall_string(const struct cap_wire_datum *d, char* value, int *len);
+int cap_unmarshall_capbox(const struct cap_wire_datum *d, struct capbox_options *options);
+
-/* Sending, with or without file descriptors */
-int cap_send(int sock, char *name, struct cap_wire_datum *d);
-int cap_send_fd(int sock, const char *name, struct cap_wire_datum *d,
+/* Sending, with (_fd) or without file descriptors */
+int cap_send(int sock, struct cap_wire_datum *d);
+int cap_send_fd(int sock, struct cap_wire_datum *d,
int32_t fd_array[], int32_t fdlen);
+int cap_send_message(int sock, struct cap_wire_datum *data[], int len);
+
/* Receiving, with or without file descriptors */
-int cap_recv(int sock, char **name, struct cap_wire_datum **d);
+struct cap_wire_datum* cap_recv(int sock);
/* You supply the FD array and say how big it is; I'll tell you how many FDs you actually received. */
-int cap_recv_fd(int sock, char **name, struct cap_wire_datum **d,
- int32_t fd_array[], int32_t *fdlen);
-
+struct cap_wire_datum* cap_recv_fds(int sock, int32_t fd_array[], int32_t *fdlen);
-int cap_send_int(int client, int value);
-int cap_recv_int(int client, int *value);
-
-int cap_send_string(int client, char *value, int len);
-int cap_recv_string(int client, char **value);
-
-int cap_send_capbox_options(int client, struct capbox_options *options);
-int cap_recv_capbox_options(int client, struct capbox_options *options);
-
==== //depot/projects/trustedbsd/capabilities/src/tools/cap/user_angel/server.c#4 (text+ko) ====
@@ -31,9 +31,6 @@
* SUCH DAMAGE.
*/
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
#include <sys/capability.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -46,7 +43,6 @@
#include <unistd.h>
#include "cap.h"
-#include "fdcomm.h"
#include "protocol.h"
#include "server.h"
@@ -55,9 +51,8 @@
int shutting_down = 0;
char control_socket_name[256] = "";
-int *clients;
-int clientslen;
-int clientsmaxlen;
+struct fd_set sockets;
+int highest_fd;
void user_angel_server_shutdown(void)
@@ -76,15 +71,13 @@
int bind_to_path(const char *path);
void accept_client(int fd_server);
void service_clients(void);
+void serve(int fd_server, struct fd_set *sockets);
+void client_closed(int client);
int run_server(const char* address)
{
- clientslen = 0;
- clients = (int*) malloc (128 * sizeof(int));
- clientsmaxlen = 128;
-
strcpy(control_socket_name, address);
printf("Creating control socket at %s...\n", control_socket_name);
@@ -97,12 +90,7 @@
}
- while(fd_control)
- {
- accept_client(fd_control);
- service_clients();
- }
-
+ while(fd_control) serve(fd_control, &sockets);
user_angel_server_shutdown();
return 0;
@@ -111,13 +99,15 @@
int bind_to_path(const char *path)
{
+ FD_ZERO(&sockets);
+
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, control_socket_name);
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
- if(fd == 0)
+ if(fd < 0)
{
if(shutting_down) return 0;
@@ -126,6 +116,12 @@
return -1;
}
+ highest_fd = fd;
+
+/*
+ TODO: do this?
+ rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&on, sizeof(on));*/
if(bind(fd, (struct sockaddr*) &addr, sizeof(struct sockaddr_un)))
{
@@ -148,7 +144,7 @@
// non-blocking socket I/O
- int flags = fcntl(fd, F_GETFL, 0);
+/* int flags = fcntl(fd, F_GETFL, 0);
if(flags < 0)
{
perror("Error getting flags for control socket");
@@ -159,7 +155,10 @@
{
perror("Error setting flags on control socket");
return -1;
- }
+ }*/
+
+ FD_SET(fd, &sockets);
+
return fd;
@@ -185,116 +184,208 @@
return;
}
- printf("Accepted client: FD %i\n", client);
+ printf("Client %4i: Accepted\n", client);
- clients[clientslen++] = client;
+ FD_SET(client, &sockets);
+ if(client > highest_fd) highest_fd = client;
- if(clientslen == clientsmaxlen)
- {
- int newsize = 2 * clientsmaxlen;
- int *newclients = (int*) malloc(newsize * sizeof(int));
+ char hello[80];
+ sprintf(hello, "user_angel v%s", VERSION);
+ struct cap_wire_datum *d = cap_marshall_string(hello, strlen(hello));
- memcpy(newclients, clients, clientslen * sizeof(int));
- free(clients);
- clients = newclients;
- clientslen = newsize;
- }
+ cap_send(client, d);
+ free(d);
}
-void service_clients(void)
+
+void serve(int fd_server, struct fd_set *sockets)
{
- enum capangel_req_t req;
+ struct fd_set selected;
+ memcpy(&selected, sockets, sizeof(*sockets));
+
- for(int i = 0; i < clientslen; i++)
+ int ready = select(highest_fd + 1, &selected, NULL, NULL, NULL);
+ if(ready < 0)
+ {
+ perror("select() failed");
+ return;
+ }
+ else if(ready == 0)
{
- int client = clients[i];
- if(client == -1) continue;
+ perror("select() timed out");
+ return;
+ }
- int bytes = cap_recv_int(client, (int*) &req);
-
- if(bytes > 0)
+ for(int i = 0; (i <= highest_fd) && (ready > 0); i++)
+ {
+ if(FD_ISSET(i, &selected))
{
- if(handle_request(client, req))
+ if(i == fd_server) accept_client(i);
+ else
{
- perror("Error handling client request");
- close(client);
- clients[i] = -1;
+ enum capangel_req_t req;
+ struct cap_wire_datum *d = cap_recv(i);
+
+ if(!d)
+ {
+ if((errno == ENOENT) || (errno == ECONNRESET)) client_closed(i);
+ else perror("Error receiving from client");
+
+ continue;
+ }
+
+
+ int bytes = 0;
+ if(sizeof(enum capangel_req_t) == sizeof(int32_t))
+ bytes = cap_unmarshall_int(d, (int32_t*) &req);
+
+ else
+ {
+ fprintf(stderr, "enum size is %iB\n", sizeof(enum capangel_req_t));
+ return;
+ }
+
+ if(bytes < 0)
+ {
+ fprintf(stderr, "Error unmarshalling request: %s\n", cap_error());
+ continue;
+ }
+
+ if(handle_request(i, req))
+ {
+ perror("Error handling client request");
+ client_closed(i);
+ }
}
- }
- else if(errno == EAGAIN) continue;
- else
- {
- if(shutting_down) return;
- perror("Error recv()'ing from client");
- break;
+ ready--;
}
}
}
-
int handle_request(int client, enum capangel_req_t req)
{
- printf("Client %i requests ", client);
+ printf("Client %4i: ", client);
+
+ struct cap_wire_datum *d;
+ int pathlen = 256;
+ char path[pathlen];
+ int fds[32];
+ int fdlen;
switch(req)
{
case FD_FROM_PATH:
>>> TRUNCATED FOR MAIL (1000 lines) <<<
More information about the p4-projects
mailing list