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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * $FreeBSD: src/lib/libcompat/4.3/rexec.c,v 1.5.8.3 2000/11/22 13:36:00 ben Exp $
34 * $DragonFly: src/lib/libcompat/4.3/rexec.c,v 1.6 2008/10/05 18:26:41 swildner Exp $
36 * @(#)rexec.c 8.1 (Berkeley) 6/4/93
39 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/param.h>
45 #include <netinet/in.h>
58 char *getpass(), *getlogin();
61 * Options and other state info.
64 char mac_name
[9]; /* macro name */
65 char *mac_start
; /* start of macro in macbuf */
66 char *mac_end
; /* end of macro in macbuf */
69 int macnum
; /* number of defined macros */
70 struct macel macros
[16];
83 static char tokval
[100];
85 static struct toktab
{
89 { "default", DEFAULT
},
91 { "password", PASSWD
},
93 { "account", ACCOUNT
},
106 if (feof(cfile
) || ferror(cfile
))
108 while ((c
= getc(cfile
)) != EOF
&&
109 (c
== '\n' || c
== '\t' || c
== ' ' || c
== ','))
115 while ((c
= getc(cfile
)) != EOF
&& c
!= '"') {
122 while ((c
= getc(cfile
)) != EOF
123 && c
!= '\n' && c
!= '\t' && c
!= ' ' && c
!= ',') {
132 for (t
= toktab
; t
->tokstr
; t
++)
133 if (!strcmp(t
->tokstr
, tokval
))
139 ruserpass(char *host
, char **aname
, char **apass
, char **aacct
)
141 char *hdir
, buf
[BUFSIZ
], *tmp
;
142 char myname
[MAXHOSTNAMELEN
], *mydomain
;
143 int t
, i
, c
, usedefault
= 0;
146 hdir
= getenv("HOME");
149 if (strlen(hdir
) + 8 > sizeof(buf
))
151 (void) sprintf(buf
, "%s/.netrc", hdir
);
152 cfile
= fopen(buf
, "r");
158 if (gethostname(myname
, sizeof(myname
)) < 0)
160 if ((mydomain
= strchr(myname
, '.')) == NULL
)
163 while ((t
= token())) switch(t
) {
174 * Allow match either for user's input host name
175 * or official hostname. Also allow match of
176 * incompletely-specified host in local domain.
178 if (strcasecmp(host
, tokval
) == 0)
180 if ((tmp
= strchr(host
, '.')) != NULL
&&
181 strcasecmp(tmp
, mydomain
) == 0 &&
182 strncasecmp(host
, tokval
, tmp
- host
) == 0 &&
183 tokval
[tmp
- host
] == '\0')
188 while ((t
= token()) && t
!= MACH
&& t
!= DEFAULT
) switch(t
) {
193 *aname
= malloc((unsigned) strlen(tokval
) + 1);
194 (void) strcpy(*aname
, tokval
);
196 if (strcmp(*aname
, tokval
))
201 if ((*aname
== 0 || 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
== 0) {
209 *apass
= malloc((unsigned) strlen(tokval
) + 1);
210 (void) strcpy(*apass
, tokval
);
214 if (fstat(fileno(cfile
), &stb
) >= 0
215 && (stb
.st_mode
& 077) != 0) {
216 warnx("Error: .netrc file is readable by others.");
217 warnx("Remove account or make file unreadable by others.");
220 if (token() && *aacct
== 0) {
221 *aacct
= malloc((unsigned) strlen(tokval
) + 1);
222 (void) strcpy(*aacct
, tokval
);
226 while ((c
=getc(cfile
)) != EOF
&&
227 (c
== ' ' || c
== '\t'))
229 if (c
== EOF
|| c
== '\n') {
230 printf("Missing macdef name argument.\n");
234 printf("Limit of 16 macros have already been defined\n");
237 tmp
= macros
[macnum
].mac_name
;
239 for (i
=0; i
< 8 && (c
=getc(cfile
)) != EOF
&&
244 printf("Macro definition missing null line terminator.\n");
249 while ((c
=getc(cfile
)) != EOF
&& c
!= '\n');
252 printf("Macro definition missing null line terminator.\n");
256 macros
[macnum
].mac_start
= macbuf
;
259 macros
[macnum
].mac_start
= macros
[macnum
-1].mac_end
+ 1;
261 tmp
= macros
[macnum
].mac_start
;
262 while (tmp
!= macbuf
+ 4096) {
263 if ((c
=getc(cfile
)) == EOF
) {
264 printf("Macro definition missing null line terminator.\n");
269 if (*(tmp
-1) == '\0') {
270 macros
[macnum
++].mac_end
= tmp
- 1;
277 if (tmp
== macbuf
+ 4096) {
278 printf("4K macro buffer exceeded\n");
283 warnx("Unknown .netrc keyword %s", tokval
);
289 (void) fclose(cfile
);
292 (void) fclose(cfile
);
297 rexec_af(char **ahost
, int rport
, const char *name
, const char *pass
,
298 const char *cmd
, int *fd2p
, sa_family_t
*af
)
300 struct sockaddr_storage sa2
, from
;
301 struct addrinfo hints
, *res0
;
302 const char *orig_name
= name
;
303 const char *orig_pass
= pass
;
304 static char *ahostbuf
;
309 char servbuff
[NI_MAXSERV
];
311 snprintf(servbuff
, sizeof(servbuff
), "%d", ntohs(rport
));
312 servbuff
[sizeof(servbuff
) - 1] = '\0';
314 memset(&hints
, '\0', sizeof(hints
));
315 hints
.ai_family
= af
;
316 hints
.ai_socktype
= SOCK_STREAM
;
317 hints
.ai_flags
= AI_CANONNAME
;
318 gai
= getaddrinfo(*ahost
, servbuff
, &hints
, &res0
);
320 /* XXX: set errno? */
324 if (res0
->ai_canonname
){
326 ahostbuf
= strdup (res0
->ai_canonname
);
327 if (ahostbuf
== NULL
) {
328 perror ("rexec: strdup");
334 __set_errno (ENOENT
);
337 ruserpass(res0
->ai_canonname
, &name
, &pass
, 0);
339 s
= socket(res0
->ai_family
, res0
->ai_socktype
, 0);
341 perror("rexec: socket");
344 if (connect(s
, res0
->ai_addr
, res0
->ai_addrlen
) < 0) {
345 if (errno
== ECONNREFUSED
&& timo
<= 16) {
351 perror(res0
->ai_canonname
);
355 (void) write(s
, "", 1);
362 s2
= socket(res0
->ai_family
, res0
->ai_socktype
, 0);
368 sa2len
= sizeof (sa2
);
369 if (getsockname(s2
, (struct sockaddr
*)&sa2
, &sa2len
) < 0) {
370 perror("getsockname");
373 } else if (sa2len
!= SA_LEN((struct sockaddr
*)&sa2
)) {
379 if (!getnameinfo((struct sockaddr
*)&sa2
, sa2len
,
380 NULL
, 0, servbuff
, sizeof(servbuff
),
382 port
= atoi(servbuff
);
383 (void) sprintf(num
, "%u", port
);
384 (void) write(s
, num
, strlen(num
)+1);
385 { socklen_t len
= sizeof (from
);
386 s3
= accept(s2
, (struct sockaddr
*)&from
,
398 (void) write(s
, name
, strlen(name
) + 1);
399 /* should public key encypt the password here */
400 (void) write(s
, pass
, strlen(pass
) + 1);
401 (void) write(s
, cmd
, strlen(cmd
) + 1);
403 /* We don't need the memory allocated for the name and the password
404 in ruserpass anymore. */
405 if (name
!= orig_name
)
406 free ((char *) name
);
407 if (pass
!= orig_pass
)
408 free ((char *) pass
);
410 if (read(s
, &c
, 1) != 1) {
415 while (read(s
, &c
, 1) == 1) {
416 (void) write(2, &c
, 1);
434 rexec(char **ahost
, int rport
, char *name
, char *pass
, char *cmd
, int *fd2p
)
436 struct sockaddr_in sin
, sin2
, from
;
443 hp
= gethostbyname(*ahost
);
449 ruserpass(hp
->h_name
, &name
, &pass
, &acct
);
453 s
= socket(AF_INET
, SOCK_STREAM
, 0);
455 perror("rexec: socket");
458 sin
.sin_family
= hp
->h_addrtype
;
459 sin
.sin_port
= rport
;
460 bcopy(hp
->h_addr
, (caddr_t
)&sin
.sin_addr
, hp
->h_length
);
461 if (connect(s
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
462 if (errno
== ECONNREFUSED
&& timo
<= 16) {
472 (void) write(s
, "", 1);
478 s2
= socket(AF_INET
, SOCK_STREAM
, 0);
484 sin2len
= sizeof (sin2
);
485 if (getsockname(s2
, (struct sockaddr
*)&sin2
, &sin2len
) < 0 ||
486 sin2len
!= sizeof (sin2
)) {
487 perror("getsockname");
491 port
= ntohs((u_short
)sin2
.sin_port
);
492 (void) sprintf(num
, "%u", port
);
493 (void) write(s
, num
, strlen(num
)+1);
494 { int len
= sizeof (from
);
495 s3
= accept(s2
, (struct sockaddr
*)&from
, &len
);
505 (void) write(s
, name
, strlen(name
) + 1);
506 /* should public key encypt the password here */
507 (void) write(s
, pass
, strlen(pass
) + 1);
508 (void) write(s
, cmd
, strlen(cmd
) + 1);
509 if (read(s
, &c
, 1) != 1) {
514 while (read(s
, &c
, 1) == 1) {
515 (void) write(2, &c
, 1);