a180a41bba1d50822df23fff0099e90b86638b89vboxsync/* -*- c-basic-offset: 8 -*-
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdesktop: A Remote Desktop Protocol client.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Master/Slave remote controlling
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Copyright 2013 Henrik Andersson <hean01@cendio.se> for Cendio AB
a180a41bba1d50822df23fff0099e90b86638b89vboxsync This program is free software: you can redistribute it and/or modify
a180a41bba1d50822df23fff0099e90b86638b89vboxsync it under the terms of the GNU General Public License as published by
a180a41bba1d50822df23fff0099e90b86638b89vboxsync the Free Software Foundation, either version 3 of the License, or
a180a41bba1d50822df23fff0099e90b86638b89vboxsync (at your option) any later version.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync This program is distributed in the hope that it will be useful,
a180a41bba1d50822df23fff0099e90b86638b89vboxsync but WITHOUT ANY WARRANTY; without even the implied warranty of
a180a41bba1d50822df23fff0099e90b86638b89vboxsync MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
a180a41bba1d50822df23fff0099e90b86638b89vboxsync GNU General Public License for more details.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync You should have received a copy of the GNU General Public License
a180a41bba1d50822df23fff0099e90b86638b89vboxsync along with this program. If not, see <http://www.gnu.org/licenses/>.
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * the General Public License version 2 (GPLv2) at this time for any software where
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * a choice of GPL license versions is made available with the language indicating
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * that GPLv2 or any later version may be used, or where a choice of which version
6e9aa255e3376b2da5824c09c4c62bc233463bfevboxsync * of the GPL is applied is otherwise unspecified.
a180a41bba1d50822df23fff0099e90b86638b89vboxsync#define RDESKTOP_CTRLSOCK_STORE "/.local/share/rdesktop/ctrl"
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* initialize new slave list item */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ns = (_ctrl_slave_t *) xmalloc(sizeof(_ctrl_slave_t));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* append new slave to end of list */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* find last element in list */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* if last found append new */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* no elemnts in list, lets add first */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* find slave with sock */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* shutdown socket */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* remove item from list */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync_ctrl_command_result(_ctrl_slave_t * slave, int result)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* translate and send result code back to client */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* unescape linebuffer */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (strncmp(cmd, CMD_SEAMLESS_SPAWN " ", strlen(CMD_SEAMLESS_SPAWN) + 1) == 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* process seamless spawn request */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync perror("Error creating ctrl client socket: socket()");
a180a41bba1d50822df23fff0099e90b86638b89vboxsync len = sizeof(saun.sun_family) + strlen(saun.sun_path);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* test connection */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (connect(s, (struct sockaddr *) &saun, len) != 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync_ctrl_create_hash(const char *user, const char *domain, const char *host, char *hash, size_t hsize)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* version\0user\0domain\0host\0flags */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, (uint8 *) & version, sizeof(version));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, (uint8 *) user, strlen(user));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, (uint8 *) domain, strlen(domain));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, (uint8 *) host, strlen(host));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync rdssl_sha1_update(&sha1, (uint8 *) & flags, sizeof(flags));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync/** Initialize ctrl
a180a41bba1d50822df23fff0099e90b86638b89vboxsync Ret values: <0 failure, 0 master, 1 client
a180a41bba1d50822df23fff0099e90b86638b89vboxsyncctrl_init(const char *user, const char *domain, const char *host)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* check if ctrl already initialized */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* get uniq hash for ctrlsock name */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync snprintf(ctrlsock_name, PATH_MAX, "%s" RDESKTOP_CTRLSOCK_STORE "/%s.ctl", home, hash);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* make sure that ctrlsock store path exists */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync snprintf(path, PATH_MAX, "%s" RDESKTOP_CTRLSOCK_STORE, home);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* check if ctrl socket already exist then this process becomes a client */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* verify that unix socket is not stale */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* setup ctrl socket and start listening for connections */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if ((ctrlsock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* bind and start listening on server socket */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync strncpy(saun.sun_path, ctrlsock_name, sizeof(saun.sun_path));
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (bind(ctrlsock, (struct sockaddr *) &saun, sizeof(struct sockaddr_un)) < 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* add ctrl cleanup func to exit hooks */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* add connected slaves to fd set */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* check if we got any connections on server socket */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ns = accept(ctrlsock, (struct sockaddr *) &fsaun, &fromlen);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* check if any of our slaves fds has data */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync res = recv(it->sock, it->linebuf + offs, CTRL_LINEBUF_SIZE - offs, 0);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* linebuffer full let's disconnect slave */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Check if we got full command line */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* iterate over string and check against escaped \n */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Check if newline is escaped */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* If we havent found an nonescaped \n we need more data */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* strip new linebuf and dispatch command */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Peer disconnected or socket error */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync char data[CTRL_LINEBUF_SIZE], tmp[CTRL_LINEBUF_SIZE];
a180a41bba1d50822df23fff0099e90b86638b89vboxsync perror("Error creating ctrl client socket: socket()");
a180a41bba1d50822df23fff0099e90b86638b89vboxsync len = sizeof(saun.sun_family) + strlen(saun.sun_path);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync if (connect(s, (struct sockaddr *) &saun, len) < 0)
a180a41bba1d50822df23fff0099e90b86638b89vboxsync perror("Error connecting to ctrl socket: connect()");
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* Bundle cmd and argument into string, convert to UTF-8 if needed */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync snprintf(data, CTRL_LINEBUF_SIZE, "%s %s", cmd, arg);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync ret = utils_locale_to_utf8(data, strlen(data), tmp, CTRL_LINEBUF_SIZE - 1);
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* escape the utf-8 string */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* send escaped utf-8 command to master */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync /* read result from master */
a180a41bba1d50822df23fff0099e90b86638b89vboxsync while ((c = fgetc(fp)) != EOF && index < CTRL_RESULT_SIZE && c != '\n')