Fix API.
[shishi.git] / extra / rsh-redone / rsh.c
blob5520932928b5173fa0a0e4b8ce64f18933f50664
1 /*
2 rsh.c - remote shell client
3 Copyright (C) 2003 Guus Sliepen <guus@sliepen.eu.org>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as published
7 by the Free Software Foundation.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include <stdio.h>
20 #include <stdbool.h>
21 #include <unistd.h>
22 #include <pwd.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/poll.h>
26 #include <netdb.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <fcntl.h>
31 #ifdef SHISHI
33 #include <shishi.h>
34 #include <stdlib.h>
36 #define SERVICE "host"
37 #define AUTH_OK 0
39 #endif
41 #define BUFLEN 0x10000
43 char *argv0;
45 #ifdef SHISHI
47 void
48 usage (void)
50 fprintf (stderr,
51 "Usage: %s [-46vsx] [-l user] [-p port] [user@]host command...\n",
52 argv0);
55 #else
57 void
58 usage (void)
60 fprintf (stderr,
61 "Usage: %s [-46v] [-l user] [-p port] [user@]host command...\n",
62 argv0);
65 #endif
67 /* Make sure everything gets written */
69 ssize_t
70 safewrite (int fd, const void *buf, size_t count)
72 int written = 0, result;
74 while (count)
76 result = write (fd, buf, count);
77 if (result == -1)
79 if (errno == EINTR)
80 continue;
81 else
82 return result;
84 written += result;
85 buf += result;
86 count -= result;
89 return written;
92 /* Safe and fast string building */
94 void
95 safecpy (char **dest, int *len, char *source, bool terminate)
97 while (*source && *len)
99 *(*dest)++ = *source++;
100 (*len)--;
103 if (terminate && *len)
105 *(*dest)++ = 0;
106 (*len)--;
110 #ifdef SHISHI
112 /* read encrypted data on socket */
114 readenc (Shishi * h, int sock, char *buf, int *len, char *iv, int *ivlen,
115 Shishi_key * enckey)
117 char *out;
118 char *outbis;
119 char *iv2;
121 int rc;
122 int val;
123 int outlen;
124 int dlen = 0, blocksize, enctype, hashsize;
126 /* read size of message */
127 read (sock, &dlen, sizeof (int));
129 dlen = ntohl (dlen);
130 /* if 0 put read size to 0 */
131 if (!dlen)
133 *len = dlen;
134 return SHISHI_OK;
137 /* convert size to encryption size */
138 enctype = shishi_key_type (enckey);
140 blocksize = shishi_cipher_blocksize (enctype);
141 hashsize =
142 shishi_checksum_cksumlen (shishi_cipher_defaultcksumtype (enctype));
144 dlen += blocksize - 1 + 4;
145 if (shishi_key_type (enckey) != SHISHI_DES3_CBC_HMAC_SHA1_KD)
146 dlen += hashsize;
147 else
148 dlen += blocksize;
150 dlen /= blocksize;
151 dlen *= blocksize;
153 if (shishi_key_type (enckey) == SHISHI_DES3_CBC_HMAC_SHA1_KD)
154 dlen += hashsize;
156 /* read encrypted data */
157 outbis = malloc (dlen);
158 if (outbis == NULL)
160 printf ("Malloc error!\n");
161 return 1;
164 rc = read (sock, outbis, dlen);
165 if (rc != dlen)
167 printf ("Error during read socket\n");
168 return 1;
171 /* decrypt it */
172 rc =
173 shishi_decrypt_ivupdate (h, enckey, 1026, iv, *ivlen, &iv2, ivlen, outbis,
174 dlen, &out, &outlen);
175 if (rc != SHISHI_OK)
177 printf ("decryption error\n");
178 return 1;
181 /* len = first 4 bytes of decrypted data */
182 *len = ntohl (*((int *) out));
184 /* update iv */
185 memcpy (iv, iv2, *ivlen);
187 /* Temp patch to remove 5 unidentified bytes data from server */
188 memset (buf, 0, BUFLEN);
189 if ((unsigned char) out[4] == 255)
190 val = 5 + sizeof (int);
191 else
192 val = sizeof (int);
194 /* copy decrypted data to output */
195 memcpy (buf, out + val, strlen (out + val));
198 free (out);
199 free (outbis);
201 return SHISHI_OK;
204 /* write encrypted data to socket */
206 writeenc (Shishi * h, int sock, char *buf, int wlen, int *len, char *iv,
207 int *ivlen, Shishi_key * enckey)
209 char *out;
210 char *bufbis;
212 char *iv2;
214 int rc;
215 int dlen, outlen;
217 dlen = wlen;
218 dlen = htonl (dlen);
220 /* data to encrypt = size + data */
221 bufbis = malloc (wlen + sizeof (int));
222 memcpy (bufbis, (char *) &dlen, sizeof (int));
223 memcpy (bufbis + sizeof (int), buf, wlen);
225 /* encrypt it */
226 rc =
227 shishi_encrypt_ivupdate (h, enckey, 1026, iv, *ivlen, &iv2, ivlen, bufbis,
228 wlen + sizeof (int), &out, &outlen);
229 if (rc != SHISHI_OK)
231 printf ("decryption error\n");
232 return 1;
235 free (bufbis);
237 /* data to send = original size + encrypted data */
238 bufbis = malloc (outlen + sizeof (int));
239 if (bufbis == NULL)
241 printf ("Malloc error!\n");
242 return 1;
244 memcpy (bufbis, (char *) &dlen, sizeof (int));
245 memcpy (bufbis + sizeof (int), out, outlen);
247 /* send it */
248 write (sock, bufbis, outlen + sizeof (int));
249 *len = wlen;
251 /* update iv */
252 memcpy (iv, iv2, *ivlen);
254 free (bufbis);
255 free (out);
257 return SHISHI_OK;
262 /* shishi authentication */
264 auth (Shishi * h, int verbose, const char *cname, const char *sname, int sock,
265 char *cmd, char *port, Shishi_key ** enckey, Shishi_key * deckey)
267 Shishi_ap *ap;
268 Shishi_tkt *tkt;
269 Shishi_tkts_hint hint;
271 int rc;
272 char *out;
273 int outlen;
274 int krb5len, msglen;
275 char auth;
276 /* KERBEROS 5 SENDAUTH MESSAGE */
277 char krb5sendauth[] = "KRB5_SENDAUTH_V1.0";
278 /* PROTOCOL VERSION */
279 char krb5sendclient[] = "KCMDV0.2";
280 /* to store error msg sent by server */
281 char errormsg[101];
282 char cksumdata[101];
284 /* size of KRB5 auth message */
285 krb5len = strlen (krb5sendauth) + 1;
286 msglen = htonl (krb5len);
287 safewrite (sock, &msglen, sizeof (int));
288 /* KRB5 authentication message */
289 safewrite (sock, krb5sendauth, krb5len);
290 /* size of client message */
291 krb5len = strlen (krb5sendclient) + 1;
292 msglen = htonl (krb5len);
293 safewrite (sock, &msglen, sizeof (int));
294 /* KRB5 client message */
295 safewrite (sock, krb5sendclient, krb5len);
297 /* get answer from server 0 = ok, 1 = error with message */
298 read (sock, &auth, 1);
299 if (auth)
301 read (sock, errormsg, 100);
302 errormsg[100] = '\0';
304 printf ("Error during server authentication : %s\n", errormsg);
305 return 1;
308 if (verbose)
310 printf ("Client: %s\n", cname);
311 printf ("Server: %s\n", sname);
314 /* Get a ticket for the server. */
316 memset (&hint, 0, sizeof (hint));
318 hint.client = (char *) cname;
319 hint.server = (char *) sname;
321 tkt = shishi_tkts_get (shishi_tkts_default (h), &hint);
322 if (!tkt)
324 printf ("cannot find ticket for \"%s\"\n", sname);
325 return 1;
328 if (verbose)
329 shishi_tkt_pretty_print (tkt, stderr);
331 /* Create Authentication context */
333 rc = shishi_ap_tktoptions (h, &ap, tkt, SHISHI_APOPTIONS_MUTUAL_REQUIRED);
334 if (rc != SHISHI_OK)
336 printf ("cannot create authentication context\n");
337 return 1;
341 /* checksum = port: terminal name */
343 snprintf (cksumdata, 100, "%s:%s%s", port, cmd, cname);
345 /* add checksum to authenticator */
347 shishi_ap_authenticator_cksumdata_set (ap, cksumdata, strlen (cksumdata));
348 /* To be compatible with MIT rlogind */
349 shishi_ap_authenticator_cksumtype_set (ap, SHISHI_RSA_MD5);
351 /* create der encoded AP-REQ */
353 rc = shishi_ap_req_der (ap, &out, &outlen);
354 if (rc != SHISHI_OK)
356 printf ("cannot build authentication request: %s\n",
357 shishi_strerror (rc));
359 return 1;
362 if (verbose)
363 shishi_authenticator_print (h, stderr, shishi_ap_authenticator (ap));
365 /* extract subkey if present from ap exchange for secure connection */
367 shishi_authenticator_get_subkey (h, shishi_ap_authenticator (ap), enckey);
369 /* send size of AP-REQ to the server */
371 msglen = htonl (outlen);
372 safewrite (sock, (char *) &msglen, sizeof (int));
374 /* send AP-REQ to the server */
376 safewrite (sock, out, outlen);
378 /* read a respond from server - what ? */
380 read (sock, &auth, sizeof (int));
382 /* For mutual authentication, wait for server reply. */
384 if (shishi_apreq_mutual_required_p (h, shishi_ap_req (ap)))
386 if (verbose)
387 printf ("Waiting for server to authenticate itself...\n");
389 /* read size of the AP-REP */
391 read (sock, (char *) &outlen, sizeof (int));
393 /* read AP-REP */
394 outlen = ntohl (outlen);
395 outlen = read (sock, out, outlen);
397 rc = shishi_ap_rep_verify_der (ap, out, outlen);
398 if (rc == SHISHI_OK)
400 if (verbose)
401 printf ("AP-REP verification OK...\n");
403 else
405 if (rc == SHISHI_APREP_VERIFY_FAILED)
406 printf ("AP-REP verification failed...\n");
407 else
408 printf ("AP-REP verification error: %s\n", shishi_strerror (rc));
409 return 1;
412 /* The server is authenticated. */
413 if (verbose)
414 printf ("Server authenticated.\n");
417 /* We are now authenticated. */
418 if (verbose)
419 printf ("User authenticated.\n");
421 return AUTH_OK;
425 #endif
428 main (int argc, char **argv)
430 char *user = NULL;
431 char *luser = NULL;
432 char *host = NULL;
433 char *port = "shell";
434 char *p;
435 char lport[5];
437 struct passwd *pw;
439 int af = AF_UNSPEC;
440 struct addrinfo hint, *ai, *aip, *lai;
441 struct sockaddr raddr;
442 int raddrlen;
443 int err, sock = -1, lsock = -1, esock = -1, i;
445 int opt;
447 bool verbose = false;
449 char hostaddr[NI_MAXHOST];
450 char portnr[NI_MAXSERV];
452 char buf[3][BUFLEN], *bufp[3];
453 int len[3], wlen;
455 fd_set infd, outfd, infdset, outfdset, errfd;
456 int maxfd;
458 int flags;
460 #ifdef SHISHI
462 Shishi *h;
463 Shishi_key *enckey = NULL, *deckey = NULL;
464 int rc;
465 char *sname = NULL;
466 int shishi = 0;
467 int encryption = 0;
468 int auth2 = 0;
469 char *cmd, *tcmd;
470 int hostlen, cmdlen;
471 struct hostent *hostdata;
472 char *iv = NULL;
473 char *iv2 = NULL;
474 char *iv3 = NULL;
475 int ivlen;
476 int ivlen2;
477 int ivlen3;
479 #endif
481 argv0 = argv[0];
483 /* Lookup local username */
485 if (!(pw = getpwuid (getuid ())))
487 fprintf (stderr, "%s: Could not lookup username: %s\n", argv0,
488 strerror (errno));
489 return 1;
492 /* Process options */
494 #ifdef SHISHI
495 while ((opt = getopt (argc, argv, "+l:p:46vsx")) != -1)
496 #else
497 while ((opt = getopt (argc, argv, "+l:p:46v")) != -1)
498 #endif
501 switch (opt)
503 case 'l':
504 user = optarg;
505 break;
506 case 'p':
507 port = optarg;
508 break;
509 case '4':
510 af = AF_INET;
511 break;
512 case '6':
513 af = AF_INET6;
514 break;
515 case 'v':
516 verbose = true;
517 break;
518 #ifdef SHISHI
519 case 's':
520 shishi = 1;
521 port = "544";
522 break;
523 case 'x':
524 shishi = 1;
525 encryption = 1;
526 port = "544";
527 break;
528 #endif
529 default:
530 fprintf (stderr, "%s: Unknown option!\n", argv0);
531 usage ();
532 return 1;
536 if (optind == argc)
538 fprintf (stderr, "%s: No host specified!\n", argv0);
539 usage ();
540 return 1;
543 #ifdef SHISHI
545 if (!shishi)
547 luser = pw->pw_name;
548 if (!user)
549 user = luser;
551 #endif
553 host = argv[optind++];
555 if ((p = strchr (host, '@')))
557 user = host;
558 *p = '\0';
559 host = p + 1;
562 /* Resolve hostname and try to make a connection */
564 memset (&hint, '\0', sizeof (hint));
565 hint.ai_family = af;
566 hint.ai_socktype = SOCK_STREAM;
568 err = getaddrinfo (host, port, &hint, &ai);
570 if (err)
572 fprintf (stderr, "%s: Error looking up host: %s\n", argv0,
573 gai_strerror (err));
574 return 1;
577 hint.ai_flags = AI_PASSIVE;
579 for (aip = ai; aip; aip = aip->ai_next)
581 if (getnameinfo
582 (aip->ai_addr, aip->ai_addrlen, hostaddr, sizeof (hostaddr), portnr,
583 sizeof (portnr), NI_NUMERICHOST | NI_NUMERICSERV))
585 fprintf (stderr, "%s: Error resolving address: %s\n", argv0,
586 strerror (errno));
587 return 1;
589 if (verbose)
590 fprintf (stderr, "Trying %s port %s...", hostaddr, portnr);
592 if ((sock =
593 socket (aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1)
595 if (verbose)
596 fprintf (stderr, " Could not open socket: %s\n",
597 strerror (errno));
598 continue;
601 hint.ai_family = aip->ai_family;
603 /* Bind to a privileged port */
605 for (i = 1023; i >= 512; i--)
607 snprintf (lport, sizeof (lport), "%d", i);
608 err = getaddrinfo (NULL, lport, &hint, &lai);
609 if (err)
611 fprintf (stderr, " Error looking up localhost: %s\n",
612 gai_strerror (err));
613 return 1;
616 err = bind (sock, lai->ai_addr, lai->ai_addrlen);
618 freeaddrinfo (lai);
620 if (err)
621 continue;
622 else
623 break;
626 if (err)
628 if (verbose)
629 fprintf (stderr, " Could not bind to privileged port: %s\n",
630 strerror (errno));
631 continue;
634 if (connect (sock, aip->ai_addr, aip->ai_addrlen) == -1)
636 if (verbose)
637 fprintf (stderr, " Connection failed: %s\n", strerror (errno));
638 continue;
640 if (verbose)
641 fprintf (stderr, " Connected.\n");
642 break;
645 if (!aip)
647 fprintf (stderr, "%s: Could not make a connection.\n", argv0);
648 return 1;
651 /* Create a socket for the incoming connection for stderr output */
653 if ((lsock =
654 socket (aip->ai_family, aip->ai_socktype, aip->ai_protocol)) == -1)
656 fprintf (stderr, "%s: Could not open socket: %s\n", argv0,
657 strerror (errno));
658 return 1;
661 hint.ai_family = aip->ai_family;
663 freeaddrinfo (ai);
665 for (i--; i >= 512; i--)
667 snprintf (lport, sizeof (lport), "%d", i);
668 err = getaddrinfo (NULL, lport, &hint, &lai);
669 if (err)
671 fprintf (stderr, "%s: Error looking up localhost: %s\n", argv0,
672 gai_strerror (err));
673 return 1;
676 err = bind (lsock, lai->ai_addr, lai->ai_addrlen);
678 freeaddrinfo (lai);
680 if (err)
681 continue;
682 else
683 break;
686 if (err)
688 fprintf (stderr, "%s: Could not bind to privileged port: %s\n", argv0,
689 strerror (errno));
690 return 1;
693 if (listen (lsock, 1))
695 fprintf (stderr, "%s: Could not listen: %s\n", argv0, strerror (errno));
696 return 1;
699 /* Drop privileges */
701 if (setuid (getuid ()))
703 fprintf (stderr, "%s: Unable to drop privileges: %s\n", argv0,
704 strerror (errno));
705 return 1;
708 /* Send required information to the server */
710 bufp[0] = buf[0];
711 len[0] = sizeof (buf[0]);
712 #ifdef SHISHI
714 if (shishi)
716 if (!shishi_check_version (SHISHI_VERSION))
718 printf ("shishi_check_version() failed:\n"
719 "Header file incompatible with shared library.\n");
720 return 1;
723 rc = shishi_init (&h);
724 if (rc != SHISHI_OK)
726 printf ("error initializing shishi: %s\n", shishi_strerror (rc));
727 return 1;
730 hostdata = gethostbyname (host);
731 hostlen = strlen (hostdata->h_name) + strlen (SERVICE) + 2;
732 sname = malloc (hostlen);
733 snprintf (sname, hostlen, "%s/%s", SERVICE, hostdata->h_name);
735 rc = optind;
736 cmdlen = BUFLEN;
737 cmd = malloc (cmdlen);
738 tcmd = cmd;
740 if (encryption)
741 safecpy (&tcmd, &cmdlen, "-x ", 0);
743 for (; optind < argc; optind++)
745 safecpy (&tcmd, &cmdlen, argv[optind], 0);
746 if (optind < argc - 1)
747 safecpy (&tcmd, &cmdlen, " ", 0);
750 safecpy (&tcmd, &cmdlen, "", 1);
752 optind = rc;
754 if (!user)
755 user = (char *) shishi_principal_default (h);
757 safewrite (sock, lport, strlen (lport) + 1);
759 /* Wait for incoming connection from server */
761 if ((esock = accept (lsock, &raddr, &raddrlen)) == -1)
763 fprintf (stderr, "%s: Could not accept stderr connection: %s\n",
764 argv0, strerror (errno));
765 return 1;
768 close (lsock);
770 if (auth (h, 0, user, sname, sock, cmd, port, &enckey, deckey) !=
771 AUTH_OK)
772 return 1;
774 free (cmd);
777 else
779 safecpy (&bufp[0], &len[0], lport, 1);
780 safecpy (&bufp[0], &len[0], luser, 1);
783 #else
784 safecpy (&bufp[0], &len[0], lport, 1);
785 safecpy (&bufp[0], &len[0], luser, 1);
786 #endif
788 safecpy (&bufp[0], &len[0], user, 1);
790 #ifdef SHISHI
791 if (encryption)
792 safecpy (&bufp[0], &len[0], "-x ", 0);
793 #endif
795 for (; optind < argc; optind++)
797 safecpy (&bufp[0], &len[0], argv[optind], 0);
798 if (optind < argc - 1)
799 safecpy (&bufp[0], &len[0], " ", 0);
802 #ifdef SHISHI
803 if (shishi)
805 safecpy (&bufp[0], &len[0], "", 1);
806 safecpy (&bufp[0], &len[0], user, 1);
808 else
809 #endif
811 safecpy (&bufp[0], &len[0], "", 1);
813 if (!len[0])
815 fprintf (stderr, "%s: Arguments too long!\n", argv0);
816 return 1;
819 if (safewrite (sock, buf[0], bufp[0] - buf[0]) == -1)
821 fprintf (stderr, "%s: Unable to send required information: %s\n", argv0,
822 strerror (errno));
823 return 1;
826 #ifdef SHISHI
828 if (shishi)
830 safewrite (sock, &auth2, sizeof (int));
832 #endif
834 /* Wait for acknowledgement from server */
836 errno = 0;
838 if (read (sock, buf[0], 1) != 1 || *buf[0])
840 fprintf (stderr, "%s: Didn't receive NULL byte from server: %s\n",
841 argv0, strerror (errno));
842 return 1;
845 #ifdef SHISHI
847 if (encryption)
849 ivlen = ivlen2 = ivlen3 = shishi_key_length (enckey);
850 iv = malloc (ivlen);
851 memset (iv, 1, ivlen);
852 iv2 = malloc (ivlen2);
853 memset (iv2, 3, ivlen2);
854 iv3 = malloc (ivlen3);
855 memset (iv3, 0, ivlen3);
858 if (!shishi)
861 /* Wait for incoming connection from server */
863 if ((esock = accept (lsock, &raddr, &raddrlen)) == -1)
865 fprintf (stderr, "%s: Could not accept stderr connection: %s\n",
866 argv0, strerror (errno));
867 return 1;
870 close (lsock);
873 #else
875 /* Wait for incoming connection from server */
877 if ((esock = accept (lsock, &raddr, &raddrlen)) == -1)
879 fprintf (stderr, "%s: Could not accept stderr connection: %s\n", argv0,
880 strerror (errno));
881 return 1;
884 close (lsock);
886 #endif
888 /* Process input/output */
890 flags = fcntl (sock, F_GETFL);
891 fcntl (sock, F_SETFL, flags | O_NONBLOCK);
892 flags = fcntl (esock, F_GETFL);
893 fcntl (esock, F_SETFL, flags | O_NONBLOCK);
895 bufp[0] = buf[0];
896 bufp[1] = buf[1];
897 bufp[2] = buf[2];
899 FD_ZERO (&infdset);
900 FD_ZERO (&outfdset);
901 FD_SET (0, &infdset);
902 FD_SET (sock, &infdset);
903 FD_SET (esock, &infdset);
905 maxfd = (sock > esock ? sock : esock) + 1;
907 for (;;)
909 errno = 0;
910 infd = infdset;
911 outfd = outfdset;
912 errfd = infdset;
914 if (select (maxfd, &infd, &outfd, &errfd, NULL) <= 0)
916 if (errno == EINTR)
917 continue;
918 else
919 break;
923 if (FD_ISSET (esock, &infd))
925 #ifdef SHISHI
926 if (encryption)
928 rc = readenc (h, esock, buf[2], &len[2], iv2, &ivlen2, enckey);
929 if (rc != SHISHI_OK)
930 break;
932 else
933 #endif
934 len[2] = read (esock, buf[2], BUFLEN);
935 if (len[2] <= 0)
937 if (errno != EINTR)
939 if (FD_ISSET (sock, &infdset) || FD_ISSET (1, &outfdset))
940 FD_CLR (esock, &infdset);
941 else
942 break;
945 else
947 FD_SET (2, &outfdset);
948 FD_CLR (esock, &infdset);
952 if (FD_ISSET (2, &outfd))
954 wlen = write (2, bufp[2], len[2]);
955 if (wlen <= 0)
957 if (errno != EINTR)
959 if (FD_ISSET (sock, &infdset) || FD_ISSET (1, &outfdset))
960 FD_CLR (esock, &infdset);
961 else
962 break;
965 else
967 len[2] -= wlen;
968 bufp[2] += wlen;
969 if (!len[2])
971 FD_CLR (2, &outfdset);
972 FD_SET (esock, &infdset);
973 bufp[2] = buf[2];
978 if (FD_ISSET (sock, &infd))
980 #ifdef SHISHI
981 if (encryption)
983 rc = readenc (h, sock, buf[1], &len[1], iv, &ivlen, enckey);
984 if (rc != SHISHI_OK)
985 break;
987 else
988 #endif
989 len[1] = read (sock, buf[1], BUFLEN);
990 if (len[1] <= 0)
992 if (errno != EINTR)
994 if (FD_ISSET (esock, &infdset) || FD_ISSET (2, &outfdset))
995 FD_CLR (sock, &infdset);
996 else
997 break;
1000 else
1002 FD_SET (1, &outfdset);
1003 FD_CLR (sock, &infdset);
1007 if (FD_ISSET (1, &outfd))
1009 wlen = write (1, bufp[1], len[1]);
1010 if (wlen <= 0)
1012 if (errno != EINTR)
1014 if (FD_ISSET (esock, &infdset) || FD_ISSET (2, &outfdset))
1015 FD_CLR (sock, &infdset);
1016 else
1017 break;
1020 else
1022 len[1] -= wlen;
1023 bufp[1] += wlen;
1024 if (!len[1])
1026 FD_CLR (1, &outfdset);
1027 FD_SET (sock, &infdset);
1028 bufp[1] = buf[1];
1033 if (FD_ISSET (0, &infd))
1035 len[0] = read (0, buf[0], BUFLEN);
1036 if (len[0] <= 0)
1038 if (errno != EINTR)
1040 FD_CLR (0, &infdset);
1041 shutdown (sock, SHUT_WR);
1044 else
1046 FD_SET (sock, &outfdset);
1047 FD_CLR (0, &infdset);
1051 if (FD_ISSET (sock, &outfd))
1053 #ifdef SHISHI
1054 if (encryption)
1056 rc =
1057 writeenc (h, sock, bufp[0], len[0], &wlen, iv3, &ivlen3,
1058 enckey);
1059 if (rc != SHISHI_OK)
1060 break;
1062 else
1063 #endif
1064 wlen = write (sock, bufp[0], len[0]);
1065 if (wlen <= 0)
1067 if (errno != EINTR)
1068 break;
1070 else
1072 len[0] -= wlen;
1073 bufp[0] += wlen;
1074 if (!len[0])
1076 FD_CLR (sock, &outfdset);
1077 FD_SET (0, &infdset);
1078 bufp[0] = buf[0];
1086 if (errno)
1088 fprintf (stderr, "%s: %s\n", argv0, strerror (errno));
1089 return 1;
1092 close (sock);
1093 close (esock);
1095 #ifdef SHISHI
1097 if (shishi)
1099 shishi_done (h);
1100 if (encryption)
1102 free (iv);
1103 free (iv2);
1104 free (iv3);
1108 #endif
1110 return 0;