2 * Copyright (c) 1980, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * $FreeBSD: src/lib/libcompat/4.3/rexec.c,v 1.5.8.3 2000/11/22 13:36:00 ben Exp $
31 * @(#)rexec.c 8.1 (Berkeley) 6/4/93
34 #include <sys/types.h>
36 #include <sys/socket.h>
37 #include <sys/param.h>
40 #include <netinet/in.h>
51 #define SA_LEN(addr) ((addr)->sa_len)
52 #define __set_errno(val) errno = (val)
55 char *getpass(), *getlogin();
58 * Options and other state info.
61 char mac_name
[9]; /* macro name */
62 char *mac_start
; /* start of macro in macbuf */
63 char *mac_end
; /* end of macro in macbuf */
66 int macnum
; /* number of defined macros */
67 struct macel macros
[16];
80 static char tokval
[100];
82 static struct toktab
{
86 { "default", DEFAULT
},
88 { "password", PASSWD
},
90 { "account", ACCOUNT
},
103 if (feof(cfile
) || ferror(cfile
))
105 while ((c
= getc(cfile
)) != EOF
&&
106 (c
== '\n' || c
== '\t' || c
== ' ' || c
== ','))
112 while ((c
= getc(cfile
)) != EOF
&& c
!= '"') {
119 while ((c
= getc(cfile
)) != EOF
120 && c
!= '\n' && c
!= '\t' && c
!= ' ' && c
!= ',') {
129 for (t
= toktab
; t
->tokstr
; t
++)
130 if (!strcmp(t
->tokstr
, tokval
))
136 ruserpass(char *host
, const char **aname
, const char **apass
, char **aacct
)
138 char *hdir
, buf
[BUFSIZ
], *tmp
;
139 char myname
[MAXHOSTNAMELEN
], *mydomain
;
140 int t
, i
, c
, usedefault
= 0;
143 hdir
= getenv("HOME");
146 if (strlen(hdir
) + 8 > sizeof(buf
))
148 (void) sprintf(buf
, "%s/.netrc", hdir
);
149 cfile
= fopen(buf
, "r");
155 if (gethostname(myname
, sizeof(myname
)) < 0)
157 if ((mydomain
= strchr(myname
, '.')) == NULL
)
160 while ((t
= token())) switch(t
) {
171 * Allow match either for user's input host name
172 * or official hostname. Also allow match of
173 * incompletely-specified host in local domain.
175 if (strcasecmp(host
, tokval
) == 0)
177 if ((tmp
= strchr(host
, '.')) != NULL
&&
178 strcasecmp(tmp
, mydomain
) == 0 &&
179 strncasecmp(host
, tokval
, tmp
- host
) == 0 &&
180 tokval
[tmp
- host
] == '\0')
185 while ((t
= token()) && t
!= MACH
&& t
!= DEFAULT
) switch(t
) {
189 if (*aname
== NULL
) {
191 tmp
= malloc(strlen(tokval
) + 1);
195 if (strcmp(*aname
, tokval
))
201 if ((*aname
== NULL
|| strcmp(*aname
, "anonymous")) &&
202 fstat(fileno(cfile
), &stb
) >= 0 &&
203 (stb
.st_mode
& 077) != 0) {
204 warnx("Error: .netrc file is readable by others.");
205 warnx("Remove password or make file unreadable by others.");
208 if (token() && *apass
== NULL
) {
210 tmp
= malloc(strlen(tokval
) + 1);
216 if (fstat(fileno(cfile
), &stb
) >= 0
217 && (stb
.st_mode
& 077) != 0) {
218 warnx("Error: .netrc file is readable by others.");
219 warnx("Remove account or make file unreadable by others.");
222 if (token() && *aacct
== NULL
) {
223 *aacct
= malloc((unsigned) strlen(tokval
) + 1);
224 (void) strcpy(*aacct
, tokval
);
228 while ((c
=getc(cfile
)) != EOF
&&
229 (c
== ' ' || c
== '\t'))
231 if (c
== EOF
|| c
== '\n') {
232 printf("Missing macdef name argument.\n");
236 printf("Limit of 16 macros have already been defined\n");
239 tmp
= macros
[macnum
].mac_name
;
241 for (i
=0; i
< 8 && (c
=getc(cfile
)) != EOF
&&
246 printf("Macro definition missing null line terminator.\n");
251 while ((c
=getc(cfile
)) != EOF
&& c
!= '\n');
254 printf("Macro definition missing null line terminator.\n");
258 macros
[macnum
].mac_start
= macbuf
;
261 macros
[macnum
].mac_start
= macros
[macnum
-1].mac_end
+ 1;
263 tmp
= macros
[macnum
].mac_start
;
264 while (tmp
!= macbuf
+ 4096) {
265 if ((c
=getc(cfile
)) == EOF
) {
266 printf("Macro definition missing null line terminator.\n");
271 if (*(tmp
-1) == '\0') {
272 macros
[macnum
++].mac_end
= tmp
- 1;
279 if (tmp
== macbuf
+ 4096) {
280 printf("4K macro buffer exceeded\n");
285 warnx("Unknown .netrc keyword %s", tokval
);
291 (void) fclose(cfile
);
294 (void) fclose(cfile
);
299 rexec_af(char **ahost
, int rport
, const char *name
, const char *pass
,
300 const char *cmd
, int *fd2p
, sa_family_t
*af
)
302 struct sockaddr_storage sa2
, from
;
303 struct addrinfo hints
, *res0
;
304 const char *orig_name
= name
;
305 const char *orig_pass
= pass
;
306 static char *ahostbuf
;
311 char servbuff
[NI_MAXSERV
];
313 snprintf(servbuff
, sizeof(servbuff
), "%d", ntohs(rport
));
314 servbuff
[sizeof(servbuff
) - 1] = '\0';
316 memset(&hints
, '\0', sizeof(hints
));
318 hints
.ai_family
= *af
;
319 hints
.ai_socktype
= SOCK_STREAM
;
320 hints
.ai_flags
= AI_CANONNAME
;
321 gai
= getaddrinfo(*ahost
, servbuff
, &hints
, &res0
);
323 /* XXX: set errno? */
327 if (res0
->ai_canonname
){
329 ahostbuf
= strdup (res0
->ai_canonname
);
330 if (ahostbuf
== NULL
) {
331 perror ("rexec: strdup");
337 __set_errno (ENOENT
);
340 ruserpass(res0
->ai_canonname
, &name
, &pass
, 0);
342 s
= socket(res0
->ai_family
, res0
->ai_socktype
, 0);
344 perror("rexec: socket");
347 if (connect(s
, res0
->ai_addr
, res0
->ai_addrlen
) < 0) {
348 if (errno
== ECONNREFUSED
&& timo
<= 16) {
354 perror(res0
->ai_canonname
);
358 (void) write(s
, "", 1);
365 s2
= socket(res0
->ai_family
, res0
->ai_socktype
, 0);
371 sa2len
= sizeof (sa2
);
372 if (getsockname(s2
, (struct sockaddr
*)&sa2
, &sa2len
) < 0) {
373 perror("getsockname");
376 } else if (sa2len
!= SA_LEN((struct sockaddr
*)&sa2
)) {
382 if (!getnameinfo((struct sockaddr
*)&sa2
, sa2len
,
383 NULL
, 0, servbuff
, sizeof(servbuff
),
385 port
= atoi(servbuff
);
386 (void) sprintf(num
, "%u", port
);
387 (void) write(s
, num
, strlen(num
)+1);
388 { socklen_t len
= sizeof (from
);
389 s3
= accept(s2
, (struct sockaddr
*)&from
,
401 (void) write(s
, name
, strlen(name
) + 1);
402 /* should public key encypt the password here */
403 (void) write(s
, pass
, strlen(pass
) + 1);
404 (void) write(s
, cmd
, strlen(cmd
) + 1);
406 /* We don't need the memory allocated for the name and the password
407 in ruserpass anymore. */
408 if (name
!= orig_name
)
409 free ((char *) name
);
410 if (pass
!= orig_pass
)
411 free ((char *) pass
);
413 if (read(s
, &c
, 1) != 1) {
418 while (read(s
, &c
, 1) == 1) {
419 (void) write(2, &c
, 1);
437 rexec(char **ahost
, int rport
, const char *name
, const char *pass
, char *cmd
, int *fd2p
)
439 struct sockaddr_in sin
, sin2
, from
;
446 hp
= gethostbyname(*ahost
);
452 ruserpass(hp
->h_name
, &name
, &pass
, &acct
);
456 s
= socket(AF_INET
, SOCK_STREAM
, 0);
458 perror("rexec: socket");
461 sin
.sin_family
= hp
->h_addrtype
;
462 sin
.sin_port
= rport
;
463 bcopy(hp
->h_addr
, (caddr_t
)&sin
.sin_addr
, hp
->h_length
);
464 if (connect(s
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
465 if (errno
== ECONNREFUSED
&& timo
<= 16) {
475 (void) write(s
, "", 1);
481 s2
= socket(AF_INET
, SOCK_STREAM
, 0);
487 sin2len
= sizeof (sin2
);
488 if (getsockname(s2
, (struct sockaddr
*)&sin2
, &sin2len
) < 0 ||
489 sin2len
!= sizeof (sin2
)) {
490 perror("getsockname");
494 port
= ntohs((u_short
)sin2
.sin_port
);
495 (void) sprintf(num
, "%u", port
);
496 (void) write(s
, num
, strlen(num
)+1);
497 { int len
= sizeof (from
);
498 s3
= accept(s2
, (struct sockaddr
*)&from
, &len
);
508 (void) write(s
, name
, strlen(name
) + 1);
509 /* should public key encypt the password here */
510 (void) write(s
, pass
, strlen(pass
) + 1);
511 (void) write(s
, cmd
, strlen(cmd
) + 1);
512 if (read(s
, &c
, 1) != 1) {
517 while (read(s
, &c
, 1) == 1) {
518 (void) write(2, &c
, 1);