diff options
Diffstat (limited to 'usr/src/cmd/cmd-inet/usr.bin/rcp.c')
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.bin/rcp.c | 210 |
1 files changed, 151 insertions, 59 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.bin/rcp.c b/usr/src/cmd/cmd-inet/usr.bin/rcp.c index b21f426e69..7b76b8967a 100644 --- a/usr/src/cmd/cmd-inet/usr.bin/rcp.c +++ b/usr/src/cmd/cmd-inet/usr.bin/rcp.c @@ -1,5 +1,5 @@ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2005 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -52,6 +52,7 @@ #include <sys/sendfile.h> #include <sys/sysmacros.h> #include <sys/wait.h> +#include <aclutils.h> /* * It seems like Berkeley got these from pathnames.h? @@ -83,6 +84,7 @@ static int iamremote; static int iamrecursive; static int targetshouldbedirectory; static int aclflag; +static int acl_aclflag; static int retval = 0; static int portnumber = 0; @@ -200,14 +202,14 @@ main(int argc, char *argv[]) } fflag = tflag = 0; - while ((ch = getopt(argc, argv, "axdfprtz:D:k:P:")) != EOF) { + while ((ch = getopt(argc, argv, "axdfprtz:D:k:P:Z")) != EOF) { switch (ch) { case 'd': targetshouldbedirectory = 1; break; case 'f': /* "from" */ fflag = 1; - if (aclflag) + if (aclflag | acl_aclflag) /* ok response */ (void) desrcpwrite(rem, "", 1); break; @@ -220,6 +222,9 @@ main(int argc, char *argv[]) case 't': /* "to" */ tflag = 1; break; + case 'Z': + acl_aclflag++; + break; case 'x': if (!krb5_privacy_allowed()) { (void) fprintf(stderr, gettext("rcp: " @@ -652,9 +657,7 @@ toremote(char *targ, int argc, char *argv[]) if (response() < 0) exit(1); - } - else - { + } else { /* * ACL support: try to find out if the remote @@ -663,8 +666,13 @@ toremote(char *targ, int argc, char *argv[]) * purpose. */ aclflag = 1; + acl_aclflag = 1; - (void) snprintf(bp, buffersize, "%s -t %s", + /* + * First see if the remote side will support + * both aclent_t and ace_t acl's? + */ + (void) snprintf(bp, buffersize, "%s -tZ %s", cmd_sunw, targ); rem = rcmd_af(&host, portnumber, pwd->pw_name, tuser ? tuser : pwd->pw_name, @@ -681,32 +689,49 @@ toremote(char *targ, int argc, char *argv[]) != sizeof (resp)) lostconn(); if (resp != 0) { - /* - * Not OK: - * The other side is running - * non-acl rcp. Try again with - * normal stuff - */ - aclflag = 0; + acl_aclflag = 0; (void) snprintf(bp, buffersize, - "%s -t %s", cmd, targ); + "%s -t %s", cmd_sunw, targ); + (void) close(rem); host = thost; rem = rcmd_af(&host, portnumber, - pwd->pw_name, - tuser ? tuser : - pwd->pw_name, bp, 0, - AF_INET6); + pwd->pw_name, + tuser ? tuser : pwd->pw_name, + bp, 0, AF_INET6); if (rem < 0) exit(1); - if (response() < 0) - exit(1); + + if (read(rem, &resp, sizeof (resp)) + != sizeof (resp)) + lostconn(); + if (resp != 0) { + /* + * Not OK: + * The other side is running + * non-acl rcp. Try again with + * normal stuff + */ + aclflag = 0; + (void) snprintf(bp, buffersize, + "%s -t %s", cmd, targ); + (void) close(rem); + host = thost; + rem = rcmd_af(&host, portnumber, + pwd->pw_name, + tuser ? tuser : + pwd->pw_name, bp, 0, + AF_INET6); + if (rem < 0) + exit(1); + if (response() < 0) + exit(1); + } } /* everything should be fine now */ (void) setuid(userid); } - } source(1, argv + i); } @@ -843,8 +868,9 @@ tolocal(int argc, char *argv[]) * running acl cognizant version of rcp. */ aclflag = 1; + acl_aclflag = 1; - (void) snprintf(bp, buffersize, "%s -f %s", cmd_sunw, src); + (void) snprintf(bp, buffersize, "%s -Zf %s", cmd_sunw, src); rem = rcmd_af(&host, portnumber, pwd->pw_name, suser, bp, 0, AF_INET6); @@ -862,6 +888,24 @@ tolocal(int argc, char *argv[]) if (read(rem, &resp, sizeof (resp)) != sizeof (resp)) lostconn(); if (resp != 0) { + + /* + * Try again without ace_acl support + */ + acl_aclflag = 0; + (void) snprintf(bp, buffersize, "%s -f %s", + cmd_sunw, src); + rem = rcmd_af(&host, portnumber, pwd->pw_name, suser, + bp, 0, AF_INET6); + + if (rem < 0) { + ++errs; + continue; + } + + if (read(rem, &resp, sizeof (resp)) != sizeof (resp)) + lostconn(); + /* * NOT ok: * The other side is running non-acl rcp. @@ -1118,7 +1162,7 @@ notreg: } /* ACL support: send */ - if (aclflag) { + if (aclflag | acl_aclflag) { /* get acl from f and send it over */ if (sendacl(f) == ACL_FAIL) { (void) close(f); @@ -1414,7 +1458,7 @@ sink(int argc, char *argv[]) if (buf[0] == 'D') { if (exists) { if ((stb.st_mode&S_IFMT) != S_IFDIR) { - if (aclflag) { + if (aclflag | acl_aclflag) { /* * consume acl in the pipe * fd = -1 to indicate the @@ -1439,7 +1483,7 @@ sink(int argc, char *argv[]) } /* acl support for directories */ - if (aclflag) { + if (aclflag | acl_aclflag) { int dfd; if ((dfd = open(np, O_RDONLY)) == -1) @@ -1486,7 +1530,7 @@ bad: /* * ACL support: receiving */ - if (aclflag) { + if (aclflag | acl_aclflag) { /* get acl and set it to ofd */ if (recvacl(ofd, exists, pflag) == ACL_FAIL) { (void) close(ofd); @@ -1733,49 +1777,78 @@ static int sendacl(int f) { int aclcnt; - aclent_t *aclbufp; - int aclsize; char *acltext; char buf[BUFSIZ]; + acl_t *aclp; + char acltype; + int aclerror; + int trivial; - if ((aclcnt = facl(f, GETACLCNT, 0, NULL)) < 0) { - error("can't get acl count \n"); + + aclerror = facl_get(f, ACL_NO_TRIVIAL, &aclp); + if (aclerror != 0) { + error("can't retrieve ACL: %s \n", acl_strerror(aclerror)); return (ACL_FAIL); } + /* + * if acl type is not ACLENT_T and were operating in acl_aclflag == 0 + * then don't do the malloc and facl(fd, getcntcmd,...); + * since the remote side doesn't support alternate style ACL's. + */ + + if (aclp && (acl_type(aclp) != ACLENT_T) && (acl_aclflag == 0)) { + aclcnt = MIN_ACL_ENTRIES; + acltype = 'A'; + trivial = ACL_IS_TRIVIAL; + } else { + + aclcnt = (aclp != NULL) ? acl_cnt(aclp) : 0; + + if (aclp) { + acltype = (acl_type(aclp) != ACLENT_T) ? 'Z' : 'A'; + aclcnt = acl_cnt(aclp); + trivial = (acl_flags(aclp) & ACL_IS_TRIVIAL); + } else { + acltype = 'A'; + aclcnt = MIN_ACL_ENTRIES; + trivial = ACL_IS_TRIVIAL; + } + + } + /* send the acl count over */ - (void) snprintf(buf, sizeof (buf), "A%d\n", aclcnt); + (void) snprintf(buf, sizeof (buf), "%c%d\n", acltype, aclcnt); (void) desrcpwrite(rem, buf, strlen(buf)); - /* only send acl when it is non-trivial */ - if (aclcnt > MIN_ACL_ENTRIES) { - aclsize = aclcnt * sizeof (aclent_t); - if ((aclbufp = (aclent_t *)malloc(aclsize)) == NULL) { - error("rcp: cant allocate memory: aclcnt %d\n", - aclcnt); - exit(1); - } - if (facl(f, GETACL, aclcnt, aclbufp) < 0) { - error("rcp: failed to get acl\n"); - return (ACL_FAIL); - } - acltext = acltotext(aclbufp, aclcnt); + /* + * only send acl when we have an aclp, which would + * imply its not trivial. + */ + if (aclp && (trivial != ACL_IS_TRIVIAL)) { + acltext = acl_totext(aclp); if (acltext == NULL) { error("rcp: failed to convert to text\n"); + acl_free(aclp); return (ACL_FAIL); } /* send ACLs over: send the length first */ - (void) snprintf(buf, sizeof (buf), "A%d\n", strlen(acltext)); + (void) snprintf(buf, sizeof (buf), "%c%d\n", + acltype, strlen(acltext)); (void) desrcpwrite(rem, buf, strlen(buf)); (void) desrcpwrite(rem, acltext, strlen(acltext)); free(acltext); - free(aclbufp); - if (response() < 0) + if (response() < 0) { + acl_free(aclp); return (ACL_FAIL); + } } + + if (aclp) + acl_free(aclp); return (ACL_OK); } @@ -1783,7 +1856,7 @@ sendacl(int f) * Use this routine to get acl entry count and acl text size (in bytes) */ static int -getaclinfo(int *cnt) +getaclinfo(int *cnt, int *acltype) { char buf[BUFSIZ]; char *cp; @@ -1793,7 +1866,15 @@ getaclinfo(int *cnt) cp = buf; if (desrcpread(rem, cp, 1) <= 0) return (ACL_FAIL); - if (*cp++ != 'A') { + + switch (*cp++) { + case 'A': + *acltype = 0; + break; + case 'Z': + *acltype = 1; + break; + default: error("rcp: expect an ACL record, but got %c\n", *cp); return (ACL_FAIL); } @@ -1829,15 +1910,24 @@ recvacl(int f, int exists, int preserve) int j; char *tp; char *acltext; /* external format */ - aclent_t *aclbufp; /* internal format */ + acl_t *aclp; + int acltype; + int min_entries; + int aclerror; /* get acl count */ - if (getaclinfo(&aclcnt) != ACL_OK) + if (getaclinfo(&aclcnt, &acltype) != ACL_OK) return (ACL_FAIL); - if (aclcnt > MIN_ACL_ENTRIES) { + if (acltype == 0) { + min_entries = MIN_ACL_ENTRIES; + } else { + min_entries = 1; + } + + if (aclcnt > min_entries) { /* get acl text size */ - if (getaclinfo(&aclsize) != ACL_OK) + if (getaclinfo(&aclsize, &acltype) != ACL_OK) return (ACL_FAIL); if ((acltext = malloc(aclsize + 1)) == NULL) { error("rcp: cant allocate memory: %d\n", aclsize); @@ -1858,19 +1948,21 @@ recvacl(int f, int exists, int preserve) *tp = '\0'; if (preserve || !exists) { - aclbufp = aclfromtext(acltext, &aclcnt); - if (aclbufp == NULL) { - error("rcp: failed to parse acl\n"); + aclerror = acl_fromtext(acltext, &aclp); + if (aclerror != 0) { + error("rcp: failed to parse acl : %s\n", + acl_strerror(aclerror)); return (ACL_FAIL); } + if (f != -1) { - if (facl(f, SETACL, aclcnt, aclbufp) < 0) { + if (facl_set(f, aclp) < 0) { error("rcp: failed to set acl\n"); return (ACL_FAIL); } } /* -1 means that just consume the data in the pipe */ - free(aclbufp); + acl_free(aclp); } free(acltext); (void) desrcpwrite(rem, "", 1); |