6 * Copyright (c) 1983 The Regents of the University of California.
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by the University of California, Berkeley. The name of the
15 * University may not be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 "@(#) Copyright (c) 1983 The Regents of the University of California.\n\
25 All rights reserved.\n";
28 /* based on @(#)rcp.c 5.10 (Berkeley) 9/20/88 */
40 #include <sys/param.h>
42 #include <sys/types.h>
49 #include <sys/ioctl.h>
51 #include <netinet/in.h>
75 #ifdef KRB5_KRB4_COMPAT
76 #include <kerberosIV/krb.h>
81 #define RCP_BUFSIZ 4096
84 struct sockaddr_in local, foreign; /* set up by kcmd used by v4_send_auth */
85 char *krb_realm = NULL;
86 char *krb_cache = NULL;
87 char *krb_config = NULL;
88 krb5_encrypt_block eblock; /* eblock for encrypt/decrypt */
89 krb5_context bsd_context;
91 #ifdef KRB5_KRB4_COMPAT
92 Key_schedule v4_schedule;
98 void v4_send_auth(char *, char *), try_normal(char **);
99 char **save_argv(int, char **);
103 int rcmd_stream_write(), rcmd_stream_read();
104 void usage(void), sink(int, char **),
105 source(int, char **), rsource(char *, struct stat *), verifydir(char *),
106 answer_auth(char *, char *);
107 int response(void), hosteq(char *, char *), okname(char *),
112 #define UCB_RCP "/bin/rcp"
115 #endif /* KERBEROS */
120 krb5_sigtype lostconn(int);
121 int iamremote, targetshouldbedirectory;
134 struct buffer *allocbuf(struct buffer *, int, int);
136 #define NULLBUF (struct buffer *) 0
138 void error (char *fmt, ...)
139 #if !defined (__cplusplus) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
140 __attribute__ ((__format__ (__printf__, 1, 2)))
144 #define ga() (void) rcmd_stream_write(rem, "", 1, 0)
150 char *targ, *host, *src;
151 char *suser, *tuser, *thost;
153 unsigned int cmdsiz = 30;
154 char buf[RCP_BUFSIZ], cmdbuf[30];
157 static char curhost[256];
163 krb5_error_code status;
165 char **orig_argv = save_argv(argc, argv);
166 krb5_auth_context auth_context;
167 enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
169 status = krb5_init_context(&bsd_context);
171 com_err(argv[0], status, "while initializing krb5");
176 pwd = getpwuid(userid = getuid());
178 fprintf(stderr, "who are you?\n");
182 for (argc--, argv++; argc > 0 && **argv == '-'; argc--, argv++) {
184 while (**argv) switch (*(*argv)++) {
190 case 'p': /* preserve mtimes and atimes */
198 port = htons(atoi(*argv));
209 case 'k': /* Change kerberos realm */
213 if(!(krb_realm = (char *)malloc(strlen(*argv) + 1))){
214 fprintf(stderr, "rcp: Cannot malloc.\n");
217 strcpy(krb_realm, *argv);
219 case 'c': /* Change default ccache file */
223 if(!(krb_cache = (char *)malloc(strlen(*argv) + 1))){
224 fprintf(stderr, "rcp: Cannot malloc.\n");
227 strcpy(krb_cache, *argv);
229 case 'C': /* Change default config file */
233 if(!(krb_config = (char *)malloc(strlen(*argv) + 1))){
234 fprintf(stderr, "rcp: Cannot malloc.\n");
237 strcpy(krb_config, *argv);
240 if (!strcmp (*argv, "O"))
241 kcmd_proto = KCMD_OLD_PROTOCOL;
242 else if (!strcmp (*argv, "N"))
243 kcmd_proto = KCMD_NEW_PROTOCOL;
247 #endif /* KERBEROS */
248 /* The rest of these are not for users. */
250 targetshouldbedirectory = 1;
253 case 'f': /* "from" */
255 rcmd_stream_init_normal();
256 #if defined(KERBEROS)
258 answer_auth(krb_config, krb_cache);
259 #endif /* KERBEROS */
262 source(--argc, ++argv);
267 rcmd_stream_init_normal();
268 #if defined(KERBEROS)
270 answer_auth(krb_config, krb_cache);
271 #endif /* KERBEROS */
273 sink(--argc, ++argv);
285 targetshouldbedirectory = 1;
291 sp = getservbyname("kshell", "tcp");
293 sp = getservbyname("shell", "tcp");
294 #endif /* KERBEROS */
298 fprintf(stderr, "rcp: kshell/tcp: unknown service\n");
299 try_normal(orig_argv);
301 fprintf(stderr, "rcp: shell/tcp: unknown service\n");
303 #endif /* KERBEROS */
309 if (krb_realm != NULL)
310 cmdsiz += strlen(krb_realm);
311 if (krb_cache != NULL)
312 cmdsiz += strlen(krb_cache);
313 if (krb_config != NULL)
314 cmdsiz += strlen(krb_config);
316 if ((cmd = (char *)malloc(cmdsiz)) == NULL) {
317 fprintf(stderr, "rcp: Cannot malloc.\n");
320 (void) sprintf(cmd, "%srcp %s%s%s%s%s%s%s%s%s",
321 encryptflag ? "-x " : "",
323 iamrecursive ? " -r" : "", pflag ? " -p" : "",
324 targetshouldbedirectory ? " -d" : "",
325 krb_realm != NULL ? " -k " : "",
326 krb_realm != NULL ? krb_realm : "",
327 krb_cache != NULL ? " -c " : "",
328 krb_cache != NULL ? krb_cache : "",
329 krb_config != NULL ? " -C " : "",
330 krb_config != NULL ? krb_config : "");
332 #else /* !KERBEROS */
333 (void) sprintf(cmd, "rcp%s%s%s",
334 iamrecursive ? " -r" : "", pflag ? " -p" : "",
335 targetshouldbedirectory ? " -d" : "");
336 #endif /* KERBEROS */
339 (void) sigemptyset(&sa.sa_mask);
341 sa.sa_handler = lostconn;
342 (void) sigaction(SIGPIPE, &sa, (struct sigaction *)0);
344 (void) signal(SIGPIPE, lostconn);
346 targ = colon(argv[argc - 1]);
348 /* Check if target machine is the current machine. */
350 gethostname(curhost, sizeof(curhost));
351 if (targ) { /* ... to remote */
353 if (hosteq(argv[argc - 1], curhost)) {
355 /* If so, pretend there wasn't even one given
356 * check for an argument of just "host:", it
362 argv[argc - 1] = targ;
365 argv[argc - 1] = targ;
370 /* Target machine is some remote machine */
373 thost = strchr(argv[argc - 1], '@');
376 tuser = argv[argc - 1];
379 else if (!okname(tuser))
382 thost = argv[argc - 1];
385 for (i = 0; i < argc - 1; i++) {
386 src = colon(argv[i]);
387 if (src) { /* remote to remote */
391 host = strchr(argv[i], '@');
396 suser = pwd->pw_name;
397 else if (!okname(suser))
400 #if defined(hpux) || defined(__hpux)
401 "remsh %s -l %s -n %s %s '%s%s%s:%s'",
403 "rsh %s -l %s -n %s %s '%s%s%s:%s'",
405 host, suser, cmd, src,
411 #if defined(hpux) || defined(__hpux)
412 "remsh %s -n %s %s '%s%s%s:%s'",
414 "rsh %s -n %s %s '%s%s%s:%s'",
420 (void) susystem(buf);
421 } else { /* local to remote */
424 (void) sprintf(buf, "%s -t %s",
428 authopts = AP_OPTS_MUTUAL_REQUIRED;
429 status = kcmd(&sock, &host,
440 0, /* No server seq # */
443 &auth_context, authopts,
444 0, /* Not any port # */
448 if (kcmd_proto == KCMD_NEW_PROTOCOL)
449 /* Don't fall back to less safe methods. */
451 #ifdef KRB5_KRB4_COMPAT
452 fprintf(stderr, "Trying krb4 rcp...\n");
453 if (strncmp(buf, "-x rcp", 6) == 0)
454 memcpy(buf, "rcp -x", 6);
455 status = k4cmd(&sock, &host, port,
457 tuser ? tuser : pwd->pw_name, buf,
458 0, &v4_ticket, "rcmd", krb_realm,
460 &local, &foreign, 0L, 0);
462 try_normal(orig_argv);
464 v4_send_auth(host, krb_realm);
465 rcmd_stream_init_krb4(v4_cred.session, encryptflag, 0,
468 try_normal(orig_argv);
472 krb5_boolean similar;
473 krb5_keyblock *key = &cred->keyblock;
475 status = krb5_c_enctype_compare(bsd_context,
477 cred->keyblock.enctype,
480 try_normal(orig_argv); /* doesn't return */
483 status = krb5_auth_con_getsendsubkey (bsd_context,
486 if ((status || !key) && encryptflag)
487 try_normal(orig_argv);
490 key = &cred->keyblock;
492 rcmd_stream_init_krb5(key, encryptflag, 0, 1,
497 rem = rcmd(&host, port, pwd->pw_name,
498 tuser ? tuser : pwd->pw_name,
502 #endif /* KERBEROS */
509 } else { /* ... to local */
510 if (targetshouldbedirectory)
511 verifydir(argv[argc - 1]);
512 for (i = 0; i < argc - 1; i++) {
513 src = colon(argv[i]);
514 /* Check if source machine is current machine */
517 if (hosteq(argv[i], curhost)) {
519 /* If so, pretend src machine never given */
522 error("rcp: no path given in arg: %s:\n",
530 /* not equiv, return colon */
534 if (src == 0) { /* local to local */
535 (void) sprintf(buf, "/bin/cp%s%s %s %s",
536 iamrecursive ? " -r" : "",
538 argv[i], argv[argc - 1]);
539 (void) susystem(buf);
540 } else { /* remote to local */
545 host = strchr(argv[i], '@');
550 suser = pwd->pw_name;
551 else if (!okname(suser))
555 suser = pwd->pw_name;
557 (void) sprintf(buf, "%s -f %s", cmd, src);
559 authopts = AP_OPTS_MUTUAL_REQUIRED;
560 status = kcmd(&sock, &host,
569 0, /* No server seq # */
570 (struct sockaddr_in *) 0,
572 &auth_context, authopts,
573 0, /* Not any port # */
577 if (kcmd_proto == KCMD_NEW_PROTOCOL)
578 /* Don't fall back to less safe methods. */
580 #ifdef KRB5_KRB4_COMPAT
581 fprintf(stderr, "Trying krb4 rcp...\n");
582 if (strncmp(buf, "-x rcp", 6) == 0)
583 memcpy(buf, "rcp -x", 6);
584 status = k4cmd(&sock, &host, port,
585 pwd->pw_name, suser, buf,
586 0, &v4_ticket, "rcmd", krb_realm,
588 &local, &foreign, 0L, 0);
590 try_normal(orig_argv);
592 v4_send_auth(host, krb_realm);
593 rcmd_stream_init_krb4(v4_cred.session, encryptflag, 0,
596 try_normal(orig_argv);
599 krb5_keyblock *key = &cred->keyblock;
601 if (kcmd_proto == KCMD_NEW_PROTOCOL) {
602 status = krb5_auth_con_getsendsubkey (bsd_context,
606 com_err (argv[0], status,
607 "determining subkey for session");
612 "no subkey negotiated for connection");
617 rcmd_stream_init_krb5(key, encryptflag, 0, 1, kcmd_proto);
624 if(krb5_seteuid(userid)) {
625 perror("rcp seteuid user"); errs++; exit(errs);
628 sink(1, argv+argc-1);
630 if(krb5_seteuid(0)) {
631 perror("rcp seteuid 0"); errs++; exit(errs);
635 rem = rcmd(&host, port, pwd->pw_name, suser,
639 rcmd_stream_init_normal();
641 (void) setreuid(0, userid);
642 sink(1, argv+argc-1);
643 (void) setreuid(userid, 0);
646 if(seteuid(userid)) {
647 perror("rcp seteuid user"); errs++; exit(errs);
649 sink(1, argv+argc-1);
651 perror("rcp seteuid 0"); errs++; exit(errs);
654 #endif /* KERBEROS */
670 if (stat(cp, &stb) >= 0) {
671 if ((stb.st_mode & S_IFMT) == S_IFDIR)
675 error("rcp: %s: %s.\n", cp, error_message(errno));
700 register char *cp = cp0;
707 if (!isalpha(c) && !isdigit(c) && c != '_' && c != '-')
713 fprintf(stderr, "rcp: invalid user name %s\n", cp0);
725 struct sigaction sa, isa, qsa;
727 register krb5_sigtype (bsd_context, *istat)(), (*qstat)();
730 if ((pid = vfork()) == 0) {
731 execl("/bin/sh", "sh", "-c", s, (char *)0);
736 (void) sigemptyset(&sa.sa_mask);
738 sa.sa_handler = SIG_IGN;
739 (void) sigaction(SIGINT, &sa, &isa);
740 (void) sigaction(SIGQUIT, &sa, &qsa);
742 istat = signal(SIGINT, SIG_IGN);
743 qstat = signal(SIGQUIT, SIG_IGN);
747 w = waitpid(pid, &status, 0);
749 while ((w = wait(&status)) != pid && w != -1) /*void*/ ;
755 (void) sigaction(SIGINT, &isa, (struct sigaction *)0);
756 (void) sigaction(SIGQUIT, &qsa, (struct sigaction *)0);
758 (void) signal(SIGINT, istat);
759 (void) signal(SIGQUIT, qstat);
765 void source(argc, argv)
771 static struct buffer buffer;
776 char buf[RCP_BUFSIZ];
778 for (x = 0; x < argc; x++) {
780 if ((f = open(name, 0)) < 0) {
781 error("rcp: %s: %s\n", name, error_message(errno));
784 if (fstat(f, &stb) < 0)
786 switch (stb.st_mode&S_IFMT) {
801 error("rcp: %s: not a plain file\n", name);
804 last = strrchr(name, '/');
811 * Make it compatible with possible future
812 * versions expecting microseconds.
814 (void) sprintf(buf, "T%ld 0 %ld 0\n",
815 stb.st_mtime, stb.st_atime);
816 (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
817 if (response() < 0) {
822 (void) sprintf(buf, "C%04o %ld %s\n",
823 (int) stb.st_mode&07777, (long ) stb.st_size, last);
824 (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
825 if (response() < 0) {
829 if ((bp = allocbuf(&buffer, f, RCP_BUFSIZ)) == NULLBUF) {
834 for (i = 0; i < stb.st_size; i += bp->cnt) {
836 if (i + amt > stb.st_size)
837 amt = stb.st_size - i;
838 if (readerr == 0 && read(f, bp->buf, amt) != amt)
840 (void) rcmd_stream_write(rem, bp->buf, amt, 0);
846 error("rcp: %s: %s\n", name, error_message(readerr));
859 void rsource(name, statp)
863 DIR *d = opendir(name);
870 char buf[RCP_BUFSIZ];
874 error("rcp: %s: %s\n", name, error_message(errno));
877 last = strrchr(name, '/');
883 (void) sprintf(buf, "T%ld 0 %ld 0\n",
884 statp->st_mtime, statp->st_atime);
885 (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
886 if (response() < 0) {
891 (void) sprintf(buf, "D%04lo %d %s\n", (long) statp->st_mode&07777, 0,
893 (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
894 if (response() < 0) {
898 while ((dp = readdir(d)) != NULL) {
901 if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
903 if (strlen(name) + 1 + strlen(dp->d_name) >= RCP_BUFSIZ - 1) {
904 error("%s/%s: Name too long.\n", name, dp->d_name);
907 (void) sprintf(buf, "%s/%s", name, dp->d_name);
912 (void) rcmd_stream_write(rem, "E\n", 2, 0);
920 char resp, c, rbuf[RCP_BUFSIZ], *cp = rbuf;
921 if (rcmd_stream_read(rem, &resp, 1, 0) != 1)
931 case 1: /* error, followed by err msg */
932 case 2: /* fatal error, "" */
934 if (rcmd_stream_read(rem, &c, 1, 0) != 1)
937 } while (cp < &rbuf[RCP_BUFSIZ] && c != '\n');
939 (void) write(2, rbuf, (unsigned) (cp - rbuf));
955 fprintf(stderr, "rcp: lost connection\n");
960 #if !defined(HAVE_UTIMES)
962 #include <sys/time.h>
965 * We emulate utimes() instead of utime() as necessary because
966 * utimes() is more powerful than utime(), and rcp actually tries to
967 * set the microsecond values; we don't want to take away
968 * functionality unnecessarily.
970 int utimes(file, tvp)
974 struct utimbuf times;
976 times.actime = tvp[0].tv_sec;
977 times.modtime = tvp[1].tv_sec;
978 return(utime(file, ×));
983 void sink(argc, argv)
988 mode_t mask = umask(0);
990 char *targ, *whopp, *cp;
991 int of, wrerr, exists, first;
993 unsigned int amt, count;
995 static struct buffer buffer;
999 char cmdbuf[RCP_BUFSIZ], nambuf[RCP_BUFSIZ];
1001 struct timeval tv[2];
1004 #define SCREWUP(str) { whopp = str; goto screwup; }
1009 error("rcp: ambiguous target\n");
1013 if (targetshouldbedirectory)
1016 if (stat(targ, &stb) == 0 && (stb.st_mode & S_IFMT) == S_IFDIR)
1018 for (first = 1; ; first = 0) {
1020 if (rcmd_stream_read(rem, cp, 1, 0) <= 0)
1023 SCREWUP("unexpected '\\n'");
1025 if (rcmd_stream_read(rem, cp, 1, 0) != 1)
1026 SCREWUP("lost connection");
1027 } while (*cp++ != '\n');
1029 if (cmdbuf[0] == '\01' || cmdbuf[0] == '\02') {
1031 (void) write(2, cmdbuf+1, strlen(cmdbuf+1));
1032 if (cmdbuf[0] == '\02')
1044 #define getnum(t) (t) = 0; while (isdigit((int) *cp)) (t) = (t) * 10 + (*cp++ - '0');
1048 getnum(mtime.tv_sec);
1050 SCREWUP("mtime.sec not delimited");
1051 getnum(mtime.tv_usec);
1053 SCREWUP("mtime.usec not delimited");
1054 getnum(atime.tv_sec);
1056 SCREWUP("atime.sec not delimited");
1057 getnum(atime.tv_usec);
1059 SCREWUP("atime.usec not delimited");
1063 if (*cp != 'C' && *cp != 'D') {
1065 * Check for the case "rcp remote:foo\* local:bar".
1066 * In this case, the line "No match." can be returned
1067 * by the shell before the rcp command on the remote is
1068 * executed so the ^Aerror_message convention isn't
1075 SCREWUP("expected control record");
1079 for (; cp < cmdbuf+5; cp++) {
1080 if (*cp < '0' || *cp > '7')
1081 SCREWUP("bad mode");
1082 mode = (mode << 3) | (*cp - '0');
1085 SCREWUP("mode not delimited");
1087 while (isdigit((int) *cp))
1088 size = size * 10 + (*cp++ - '0');
1090 SCREWUP("size not delimited");
1092 if(strlen(targ) + strlen(cp) + 2 >= sizeof(nambuf))
1093 SCREWUP("target name too long");
1094 (void) sprintf(nambuf, "%s%s%s", targ,
1095 *targ ? "/" : "", cp);
1097 if (strlen(targ) + 1 >= sizeof (nambuf))
1098 SCREWUP("target name too long");
1099 (void) strncpy(nambuf, targ, sizeof(nambuf) - 1);
1101 nambuf[sizeof(nambuf) - 1] = '\0';
1102 exists = stat(nambuf, &stb) == 0;
1103 if (cmdbuf[0] == 'D') {
1105 if ((stb.st_mode&S_IFMT) != S_IFDIR) {
1110 (void) chmod(nambuf, mode);
1111 } else if (mkdir(nambuf, mode) < 0)
1117 if (utimes(nambuf, tv) < 0)
1118 error("rcp: can't set times on %s: %s\n",
1119 nambuf, error_message(errno));
1123 if ((of = open(nambuf, O_WRONLY|O_CREAT, mode)) < 0) {
1125 error("rcp: %s: %s\n", nambuf, error_message(errno));
1128 if (exists && pflag) {
1130 (void) chmod(nambuf, mode);
1132 (void) fchmod(of, mode);
1136 if ((bp = allocbuf(&buffer, of, RCP_BUFSIZ)) == NULLBUF) {
1143 for (i = 0; i < size; i += RCP_BUFSIZ) {
1149 j = rcmd_stream_read(rem, cp, amt, 0);
1152 error("rcp: dropped connection");
1154 error("rcp: %s\n", error_message(errno));
1160 if (count == bp->cnt) {
1162 write(of, bp->buf, count) != count)
1168 if (count != 0 && wrerr == 0 &&
1169 write(of, bp->buf, count) != count)
1171 if (ftruncate(of, size))
1172 error("rcp: can't truncate %s: %s\n", nambuf, error_message(errno));
1177 if (utimes(nambuf, tv) < 0)
1178 error("rcp: can't set times on %s: %s\n",
1179 nambuf, error_message(errno));
1182 error("rcp: %s: %s\n", nambuf, error_message(errno));
1187 error("rcp: protocol screwup: %s\n", whopp);
1193 struct buffer *allocbuf(bp, fd, blksize)
1200 if (fstat(fd, &stb) < 0) {
1201 error("rcp: fstat: %s\n", error_message(errno));
1206 if (bp->cnt < size) {
1209 bp->buf = (char *)malloc((unsigned) size);
1211 error("rcp: malloc: out of memory\n");
1220 #ifdef HAVE_STDARG_H
1221 error(char *fmt, ...)
1224 error(fmt, va_alist)
1230 char buf[RCP_BUFSIZ], *cp = buf;
1232 #ifdef HAVE_STDARG_H
1240 (void) vsprintf(cp, fmt, ap);
1244 (void) rcmd_stream_write(rem, buf, strlen(buf), 0);
1246 (void) write(2, buf+1, strlen(buf+1));
1255 "Usage: \trcp [-PN | -PO] [-p] [-x] [-k realm] f1 f2; or:\n\trcp [-PN | -PO] [-r] [-p] [-x] [-k realm] f1 ... fn d2\n");
1257 fputs("usage: rcp [-p] f1 f2; or: rcp [-rp] f1 ... fn d2\n", stderr);
1267 struct hostent *h_ptr;
1273 /* get the official names for the two hosts */
1275 if ((h_ptr = gethostbyname(h1)) == NULL)
1277 strncpy(hname1, h_ptr->h_name, sizeof (hname1));
1278 hname1[sizeof (hname1) - 1] = '\0';
1279 if ((h_ptr = gethostbyname(h2)) == NULL)
1282 /*return if they are equal (strcmp returns 0 for equal - I return 1) */
1284 return(!strcmp(hname1, h_ptr->h_name));
1290 void try_normal(argv)
1294 #ifndef KRB5_ATHENA_COMPAT
1298 fprintf(stderr,"trying normal rcp (%s)\n", UCB_RCP);
1300 /* close all but stdin, stdout, stderr */
1301 for (i = getdtablesize(); i > 2; i--)
1303 execv(UCB_RCP, argv);
1311 char **save_argv(argc, argv)
1317 char **local_argv = (char **)calloc((unsigned) argc+1,
1318 (unsigned) sizeof(char *));
1319 /* allocate an extra pointer, so that it is initialized to NULL
1320 and execv() will work */
1321 for (i = 0; i < argc; i++)
1322 local_argv[i] = strsave(argv[i]);
1329 #define SIZEOF_INADDR SIZEOF_in_addr
1331 #define SIZEOF_INADDR sizeof(struct in_addr)
1335 /* This function is mostly vestigial, since under normal operation
1336 * the -x flag doesn't get set for the server process for encrypted
1337 * rcp. It only gets called by beta clients attempting user-to-user
1338 * authentication. */
1340 answer_auth(config_file, ccache_file)
1344 krb5_data pname_data, msg;
1345 krb5_creds creds, *new_creds;
1347 krb5_error_code status;
1348 krb5_auth_context auth_context = NULL;
1351 const char * filenames[2];
1352 filenames[1] = NULL;
1353 filenames[0] = config_file;
1354 if ((status = krb5_set_config_files(bsd_context, filenames)))
1358 memset ((char*)&creds, 0, sizeof(creds));
1360 if ((status = krb5_read_message(bsd_context, (krb5_pointer)&rem,
1364 if ((status = krb5_read_message(bsd_context, (krb5_pointer) &rem,
1365 &creds.second_ticket)))
1368 if (ccache_file == NULL) {
1369 if ((status = krb5_cc_default(bsd_context, &cc)))
1372 if ((status = krb5_cc_resolve(bsd_context, ccache_file, &cc)))
1376 if ((status = krb5_cc_get_principal(bsd_context, cc, &creds.client)))
1379 if ((status = krb5_parse_name(bsd_context, pname_data.data,
1383 krb5_free_data_contents(bsd_context, &pname_data);
1385 if ((status = krb5_get_credentials(bsd_context, KRB5_GC_USER_USER, cc,
1386 &creds, &new_creds)))
1389 if ((status = krb5_mk_req_extended(bsd_context, &auth_context,
1390 AP_OPTS_USE_SESSION_KEY,
1391 NULL, new_creds, &msg)))
1394 if ((status = krb5_write_message(bsd_context, (krb5_pointer) &rem,
1396 krb5_free_data_contents(bsd_context, &msg);
1400 rcmd_stream_init_krb5(&new_creds->keyblock, encryptflag, 0, 0,
1404 krb5_free_cred_contents(bsd_context, &creds);
1405 krb5_free_creds(bsd_context, new_creds);
1406 krb5_free_data_contents(bsd_context, &msg);
1413 char storage[2*RCP_BUFSIZ]; /* storage for the decryption */
1415 char *store_ptr = storage;
1417 #ifdef KRB5_KRB4_COMPAT
1419 v4_send_auth(host,realm)
1425 if ((realm == NULL) || (realm[0] == '\0'))
1426 realm = krb_realmofhost(host);
1427 /* this needs to be sent again, because the
1428 rcp process needs the key. the rshd has
1429 grabbed the first one. */
1430 authopts = KOPT_DO_MUTUAL;
1431 if ((rem = krb_sendauth(authopts, sock, &v4_ticket,
1433 realm, (unsigned long) getpid(),
1435 &v4_cred, v4_schedule,
1438 "KCMDV0.1")) != KSUCCESS) {
1440 "krb_sendauth mutual fail: %s\n",
1441 krb_get_err_text(rem));
1445 #endif /* KRB5_KRB4_COMPAT */
1447 #endif /* KERBEROS */