9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta Jan Cholasta <jcholast@redhat.com>
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta Copyright (C) 2012 Red Hat
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta This program is free software; you can redistribute it and/or modify
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta it under the terms of the GNU General Public License as published by
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta the Free Software Foundation; either version 3 of the License, or
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta (at your option) any later version.
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta This program is distributed in the hope that it will be useful,
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta but WITHOUT ANY WARRANTY; without even the implied warranty of
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta GNU General Public License for more details.
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta You should have received a copy of the GNU General Public License
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta along with this program. If not, see <http://www.gnu.org/licenses/>.
1e68ae21e7ae46744700753ccf28bcbcaedbe017Jan Cholasta/* connect to server using socket */
244adc327f7e29ba2c7ef60bc9f732d8fe3e68c9Simo Sorceconnect_socket(int family, struct sockaddr *addr, size_t addr_len, int *sd)
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta /* set O_NONBLOCK on standard input */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "fcntl() failed (%d): %s\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "fcntl() failed (%d): %s\n",
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta /* create socket */
d0a8981bce0c462bcd4b5db2900c0f29a40a41f0Jan Cholasta sock = socket(family, SOCK_STREAM, IPPROTO_TCP);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "socket() failed (%d): %s\n",
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta /* connect to the server */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "connect() failed (%d): %s\n",
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta /* set O_NONBLOCK on the socket */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "fcntl() failed (%d): %s\n",
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta ret = fcntl(sock, F_SETFL, flags | O_NONBLOCK);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "fcntl() failed (%d): %s\n",
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "poll() failed (%d): %s\n", ret, strerror(ret));
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta /* read from standard input & write to socket */
1e68ae21e7ae46744700753ccf28bcbcaedbe017Jan Cholasta /* read from socket & write to standard output */
1e68ae21e7ae46744700753ccf28bcbcaedbe017Jan Cholasta for (i = 0; i < 2; i++) {
1e68ae21e7ae46744700753ccf28bcbcaedbe017Jan Cholasta if (ret == EAGAIN || ret == EINTR || ret == EWOULDBLOCK) {
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "read() failed (%d): %s\n", ret, strerror(ret));
1e68ae21e7ae46744700753ccf28bcbcaedbe017Jan Cholasta } else if (res == 0) {
9d7d4458d94d0aac0a7edf999368eb18f89cb76aJakub Hrozek res = sss_atomic_write_s(i == 0 ? sock : 1, buffer, res);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "sss_atomic_write_s() failed (%d): %s\n",
1e68ae21e7ae46744700753ccf28bcbcaedbe017Jan Cholasta/* connect to server using proxy command */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_OP_FAILURE, "execv() failed (%d): %s\n",
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta { "debug", '\0', POPT_ARG_INT | POPT_ARGFLAG_DOC_HIDDEN, &pc_debug, 0,
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta _("The port to use to connect to the host"), NULL },
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta { "domain", 'd', POPT_ARG_STRING, &pc_domain, 0,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "set_locale() failed (%d): %s\n", ret, strerror(ret));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov DEBUG(SSSDBG_CRIT_FAILURE, "Not enough memory\n");
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta /* parse parameters */
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta pc = poptGetContext(NULL, argc, argv, long_options, 0);
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta poptSetOtherOptionHelp(pc, "HOST [PROXY_COMMAND]");
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta BAD_POPT_PARAMS(pc, poptStrerror(ret), ret, fini);
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta BAD_POPT_PARAMS(pc, _("Invalid port\n"), ret, fini);
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta BAD_POPT_PARAMS(pc, _("Host not specified\n"), ret, fini);
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta if (pc_args && pc_args[0] && pc_args[0][0] != '/') {
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta _("The path to the proxy command must be absolute\n"),
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta /* canonicalize hostname */
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta ai_hint.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST | AI_NUMERICSERV;
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta ret = getaddrinfo(pc_host, strport, &ai_hint, &ai);
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta ai_hint.ai_flags = AI_ADDRCONFIG | AI_CANONNAME | AI_NUMERICSERV;
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta ret = getaddrinfo(pc_host, strport, &ai_hint, &ai);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "getaddrinfo() failed (%d): %s\n", ret, gai_strerror(ret));
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "getnameinfo() failed (%d): %s\n", ret, gai_strerror(ret));
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta /* look up public keys */
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta ret = sss_ssh_get_ent(mem_ctx, SSS_SSH_GET_HOST_PUBKEYS,
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov "sss_ssh_get_ent() failed (%d): %s\n", ret, strerror(ret));
9a3e40dc49c1e38bf58e45be5adff37615f3910bJan Cholasta /* connect to server */
1e68ae21e7ae46744700753ccf28bcbcaedbe017Jan Cholasta ret = connect_proxy_command(discard_const(pc_args));
b9698ee9e8365f16aebd780087d1ef4830ea9f39Jan Cholasta } else if (ai) {
5f6232c7e6d9635c1d6b6b09f799309b6094b143Simo Sorce /* Try all IP addresses before giving up */
5f6232c7e6d9635c1d6b6b09f799309b6094b143Simo Sorce for (struct addrinfo *ti = ai; ti != NULL; ti = ti->ai_next) {
244adc327f7e29ba2c7ef60bc9f732d8fe3e68c9Simo Sorce ret = connect_socket(ti->ai_family, ti->ai_addr, ti->ai_addrlen,