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
, const char **aname
, const 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
) {
192 if (*aname
== NULL
) {
194 tmp
= malloc(strlen(tokval
) + 1);
198 if (strcmp(*aname
, tokval
))
203 if ((*aname
== 0 || strcmp(*aname
, "anonymous")) &&
204 fstat(fileno(cfile
), &stb
) >= 0 &&
205 (stb
.st_mode
& 077) != 0) {
206 warnx("Error: .netrc file is readable by others.");
207 warnx("Remove password or make file unreadable by others.");
210 if (token() && *apass
== 0) {
212 tmp
= malloc(strlen(tokval
) + 1);
218 if (fstat(fileno(cfile
), &stb
) >= 0
219 && (stb
.st_mode
& 077) != 0) {
220 warnx("Error: .netrc file is readable by others.");
221 warnx("Remove account or make file unreadable by others.");
224 if (token() && *aacct
== 0) {
225 *aacct
= malloc((unsigned) strlen(tokval
) + 1);
226 (void) strcpy(*aacct
, tokval
);
230 while ((c
=getc(cfile
)) != EOF
&&
231 (c
== ' ' || c
== '\t'))
233 if (c
== EOF
|| c
== '\n') {
234 printf("Missing macdef name argument.\n");
238 printf("Limit of 16 macros have already been defined\n");
241 tmp
= macros
[macnum
].mac_name
;
243 for (i
=0; i
< 8 && (c
=getc(cfile
)) != EOF
&&
248 printf("Macro definition missing null line terminator.\n");
253 while ((c
=getc(cfile
)) != EOF
&& c
!= '\n');
256 printf("Macro definition missing null line terminator.\n");
260 macros
[macnum
].mac_start
= macbuf
;
263 macros
[macnum
].mac_start
= macros
[macnum
-1].mac_end
+ 1;
265 tmp
= macros
[macnum
].mac_start
;
266 while (tmp
!= macbuf
+ 4096) {
267 if ((c
=getc(cfile
)) == EOF
) {
268 printf("Macro definition missing null line terminator.\n");
273 if (*(tmp
-1) == '\0') {
274 macros
[macnum
++].mac_end
= tmp
- 1;
281 if (tmp
== macbuf
+ 4096) {
282 printf("4K macro buffer exceeded\n");
287 warnx("Unknown .netrc keyword %s", tokval
);
293 (void) fclose(cfile
);
296 (void) fclose(cfile
);
301 rexec_af(char **ahost
, int rport
, const char *name
, const char *pass
,
302 const char *cmd
, int *fd2p
, sa_family_t
*af
)
304 struct sockaddr_storage sa2
, from
;
305 struct addrinfo hints
, *res0
;
306 const char *orig_name
= name
;
307 const char *orig_pass
= pass
;
308 static char *ahostbuf
;
313 char servbuff
[NI_MAXSERV
];
315 snprintf(servbuff
, sizeof(servbuff
), "%d", ntohs(rport
));
316 servbuff
[sizeof(servbuff
) - 1] = '\0';
318 memset(&hints
, '\0', sizeof(hints
));
320 hints
.ai_family
= *af
;
321 hints
.ai_socktype
= SOCK_STREAM
;
322 hints
.ai_flags
= AI_CANONNAME
;
323 gai
= getaddrinfo(*ahost
, servbuff
, &hints
, &res0
);
325 /* XXX: set errno? */
329 if (res0
->ai_canonname
){
331 ahostbuf
= strdup (res0
->ai_canonname
);
332 if (ahostbuf
== NULL
) {
333 perror ("rexec: strdup");
339 __set_errno (ENOENT
);
342 ruserpass(res0
->ai_canonname
, &name
, &pass
, 0);
344 s
= socket(res0
->ai_family
, res0
->ai_socktype
, 0);
346 perror("rexec: socket");
349 if (connect(s
, res0
->ai_addr
, res0
->ai_addrlen
) < 0) {
350 if (errno
== ECONNREFUSED
&& timo
<= 16) {
356 perror(res0
->ai_canonname
);
360 (void) write(s
, "", 1);
367 s2
= socket(res0
->ai_family
, res0
->ai_socktype
, 0);
373 sa2len
= sizeof (sa2
);
374 if (getsockname(s2
, (struct sockaddr
*)&sa2
, &sa2len
) < 0) {
375 perror("getsockname");
378 } else if (sa2len
!= SA_LEN((struct sockaddr
*)&sa2
)) {
384 if (!getnameinfo((struct sockaddr
*)&sa2
, sa2len
,
385 NULL
, 0, servbuff
, sizeof(servbuff
),
387 port
= atoi(servbuff
);
388 (void) sprintf(num
, "%u", port
);
389 (void) write(s
, num
, strlen(num
)+1);
390 { socklen_t len
= sizeof (from
);
391 s3
= accept(s2
, (struct sockaddr
*)&from
,
403 (void) write(s
, name
, strlen(name
) + 1);
404 /* should public key encypt the password here */
405 (void) write(s
, pass
, strlen(pass
) + 1);
406 (void) write(s
, cmd
, strlen(cmd
) + 1);
408 /* We don't need the memory allocated for the name and the password
409 in ruserpass anymore. */
410 if (name
!= orig_name
)
411 free ((char *) name
);
412 if (pass
!= orig_pass
)
413 free ((char *) pass
);
415 if (read(s
, &c
, 1) != 1) {
420 while (read(s
, &c
, 1) == 1) {
421 (void) write(2, &c
, 1);
439 rexec(char **ahost
, int rport
, const char *name
, const char *pass
, char *cmd
, int *fd2p
)
441 struct sockaddr_in sin
, sin2
, from
;
448 hp
= gethostbyname(*ahost
);
454 ruserpass(hp
->h_name
, &name
, &pass
, &acct
);
458 s
= socket(AF_INET
, SOCK_STREAM
, 0);
460 perror("rexec: socket");
463 sin
.sin_family
= hp
->h_addrtype
;
464 sin
.sin_port
= rport
;
465 bcopy(hp
->h_addr
, (caddr_t
)&sin
.sin_addr
, hp
->h_length
);
466 if (connect(s
, (struct sockaddr
*)&sin
, sizeof(sin
)) < 0) {
467 if (errno
== ECONNREFUSED
&& timo
<= 16) {
477 (void) write(s
, "", 1);
483 s2
= socket(AF_INET
, SOCK_STREAM
, 0);
489 sin2len
= sizeof (sin2
);
490 if (getsockname(s2
, (struct sockaddr
*)&sin2
, &sin2len
) < 0 ||
491 sin2len
!= sizeof (sin2
)) {
492 perror("getsockname");
496 port
= ntohs((u_short
)sin2
.sin_port
);
497 (void) sprintf(num
, "%u", port
);
498 (void) write(s
, num
, strlen(num
)+1);
499 { int len
= sizeof (from
);
500 s3
= accept(s2
, (struct sockaddr
*)&from
, &len
);
510 (void) write(s
, name
, strlen(name
) + 1);
511 /* should public key encypt the password here */
512 (void) write(s
, pass
, strlen(pass
) + 1);
513 (void) write(s
, cmd
, strlen(cmd
) + 1);
514 if (read(s
, &c
, 1) != 1) {
519 while (read(s
, &c
, 1) == 1) {
520 (void) write(2, &c
, 1);