int fs_incompat_renumber(int *ret) { struct ViceIoctl a_params; unsigned char buf[1024]; a_params.in_size = 0; a_params.out_size = sizeof(buf); a_params.in = 0; a_params.out = (caddr_t) buf; /* getcrypt or getinitparams */ if (pioctl(NULL, _VICEIOCTL(49), &a_params, 0) < 0) { if (errno == EINVAL) { /* not openafs or old openafs */ a_params.in_size = 0; a_params.out_size = 4; a_params.in = 0; a_params.out = (caddr_t) buf; if (pioctl(NULL, _VICEIOCTL(49), &a_params, 0) < 0) { if (errno == EINVAL) { a_params.in_size = 0; a_params.out_size = 4; a_params.in = 0; a_params.out = (caddr_t) buf; /* might be new interface */ if (pioctl(NULL, _VICEIOCTL(55), &a_params, 0) < 0) return errno; /* dunno */ *ret = 1; return 0; } else { return errno; } } *ret = 0; return 0; } else return errno; } *ret = 1; return 0; }
/* Returns 0 and fills outfid and outvv with fid and version vector for specified Coda path. If version vector is not accessible, the StoreId fields of outvv are set to -1. Garbage may be copied into outvv for non-replicated files Returns -1 after printing error msg on failures. */ int getfid(char *path, ViceFid *outfid, char *outrealm, ViceVersionVector *outvv) { int rc; struct ViceIoctl vi; char junk[2048]; vi.in = NULL; vi.in_size = 0; vi.out = junk; vi.out_size = (short) sizeof(junk); memset(junk, 0, (int) sizeof(junk)); rc = pioctl(path, _VICEIOCTL(_VIOC_GETFID), &vi, 0); /* Easy: no conflicts */ if (!rc) { memcpy(outfid, junk, sizeof(ViceFid)); memcpy(outvv, junk+sizeof(ViceFid), sizeof(ViceVersionVector)); strcpy(outrealm, junk+sizeof(ViceFid)+sizeof(ViceVersionVector)); return(0); } /* if there are conflicts then can't use this object for the repair anyway. A begin repair should have been done by this point. */ return(-1); }
/* Implements the remote setpag(2) call. Note that unlike the standard call, * here we also get back the new pag value; we need this so that the caller * can add it to its group list via setgroups() */ afs_int32 SRMTSYS_SetPag(struct rx_call *call, clientcred *creds, afs_int32 *newpag, afs_int32 *errornumber) { afs_uint32 blob[PIOCTL_HEADER]; struct ViceIoctl data; afs_int32 error; *errornumber = 0; SETCLIENTCONTEXT(blob, rx_HostOf(rx_PeerOf(rx_ConnectionOf(call))), creds->uid, creds->group0, creds->group1, PSETPAG, NFS_EXPORTER); data.in = (caddr_t) blob; data.in_size = sizeof(blob); data.out = (caddr_t) blob; data.out_size = sizeof(blob); /* force local pioctl call */ error = lpioctl(0, _VICEIOCTL(PSetClientContext), &data, 1); if (error) { if (errno == PSETPAG) { *newpag = blob[0]; /* new pag value */ } else *errornumber = errno; } return 0; }
static int NFSUnlog(afs_int32 ahost, afs_int32 auid) { afs_int32 code; afs_int32 pheader[6]; char space[1200]; struct ViceIoctl blob; /* otherwise we've got the token, now prepare to build the pioctl args */ pheader[0] = ahost; pheader[1] = auid; pheader[2] = 0; /* group low */ pheader[3] = 0; /* group high */ pheader[4] = 9; /* unlog pioctl index */ pheader[5] = 1; /* NFS protocol exporter # */ /* copy stuff in */ memcpy(space, pheader, sizeof(pheader)); /* finally setup the pioctl call's parameters */ blob.in_size = sizeof(pheader); blob.in = space; blob.out_size = 0; blob.out = NULL; code = pioctl(NULL, _VICEIOCTL(99), &blob, 0); if (code) { code = errno; } return code; }
int main(int argc, char **argv) { ViceFid fid; char realm[MAXHOSTNAMELEN+1]; char tmpfname[80]; int fd; struct ViceIoctl vioc; char space[2048]; int rc; if (argc != 2) { fprintf(stderr, "Usage: %s <inc-file-name>\n", argv[0]); exit(-1); } /* make sure object is inconsistent */ if (!IsObjInc(argv[1], &fid, realm)) { fprintf(stderr, "%s isn't inconsistent\n", argv[1]); exit(0); } /* get fid and make sure it is a file */ if (ISDIR(fid) && !FID_IsLocalDir(&fid)) { fprintf(stderr, "%s is a directory - must be removed manually\n", argv[1]); exit(-1); } /* create an empty file /tmp/REPAIR.XXXXXX */ strcpy(tmpfname, "/tmp/RMINC.XXXXXX"); if ((fd = mkstemp(tmpfname)) < 0) { fprintf(stderr, "Couldn't create /tmp file\n"); exit(-1); } close(fd); /* dorepair on the fid with an empty file */ vioc.in_size = (short)(1+strlen(tmpfname)); vioc.in = tmpfname; vioc.out_size = (short) sizeof(space); vioc.out = space; memset(space, 0, (int) sizeof(space)); rc = pioctl(argv[1], _VICEIOCTL(_VIOC_REPAIR), &vioc, 0); if (rc < 0 && errno != ETOOMANYREFS) { fprintf(stderr, "Error %d for repair\n", errno); unlink(tmpfname); exit(-1); } unlink(tmpfname); /* remove the repaired file */ if (unlink(argv[1])) { fprintf(stderr, "Couldn't remove %s\n", argv[1]); exit(-1); } exit(0); }
int IsObjInc(char *name, ViceFid *fid, char *realm) { struct GetFid { ViceFid fid; ViceVersionVector vv; char realm[MAXHOSTNAMELEN+1]; } out; struct ViceIoctl vio; struct stat statbuf; char symval[MAXPATHLEN]; int rc, n; memset(fid, 0, sizeof(ViceFid)); realm[0] = '\0'; /* what if the begin repair has been done already */ rc = stat(name, &statbuf); if (rc) { /* is it a sym link */ symval[0] = 0; rc = readlink(name, symval, MAXPATHLEN); if (rc < 0) return(0); /* it's a sym link, alright */ n = sscanf(symval, "@%x.%x.%x@%s", &fid->Volume, &fid->Vnode, &fid->Unique, realm); return(n == 4); } memset(&out, 0, sizeof(out)); vio.in = NULL; vio.in_size = 0; vio.out = (char *)&out; vio.out_size = sizeof(out); rc = pioctl(name, _VICEIOCTL(_VIOC_GETFID), &vio, 0); if (rc < 0 && errno != ETOOMANYREFS) { fprintf(stderr, "Error %d for Getfid\n", errno); return(0); } memcpy(fid, &out.fid, sizeof(ViceFid)); strcpy(realm, out.realm); if (!ISDIR(out.fid) && (statbuf.st_mode & S_IFDIR)) return(1); if (out.vv.StoreId.Host == -1) return(1); return(0); }
int main(int argc, char **argv) { struct stat statbuf; int rc; ViceFid fixfid; char fixrealm[MAXHOSTNAMELEN]; vv_t fixvv; char fixpath[MAXPATHLEN]; struct ViceIoctl vioc; char space[2048]; if (argc != 3) { fprintf(stderr, "Usage: %s <inc-file-name> <merged-file-name>\n", argv[0]); exit(-1); } /* make sure repair file exists */ rc = stat(argv[2], &statbuf); if (rc != 0) { fprintf(stderr, "Couldn't find %s(errno = %d)\n", argv[2], errno); exit(-1); } if (!(statbuf.st_mode & S_IFREG)) { fprintf(stderr, "File %s cannot be used for repair\n", argv[2]); exit(-1); } if (!getfid(argv[2], &fixfid, fixrealm, &fixvv)) sprintf(fixpath, "@%08x.%08x.%08x@%s", fixfid.Volume, fixfid.Vnode, fixfid.Unique, fixrealm); else strcpy(fixpath, argv[2]); /* do the repair */ vioc.in_size = (short)(1+strlen(fixpath)); vioc.in = fixpath; vioc.out_size = (short)sizeof(space); vioc.out = space; memset(space, 0, sizeof(space)); rc = pioctl(argv[1], _VICEIOCTL(_VIOC_REPAIR), &vioc, 0); if (rc < 0 && errno != ETOOMANYREFS) { fprintf(stderr, "Error %d for repair\n", errno); exit(-1); } if (stat(argv[1], &statbuf)) exit(-1); exit(0); }
/* Implements the remote pioctl(2) call */ afs_int32 SRMTSYS_Pioctl(struct rx_call *call, clientcred *creds, char *path, afs_int32 cmd, afs_int32 follow, rmtbulk *InData, rmtbulk *OutData, afs_int32 *errornumber) { afs_int32 error; struct ViceIoctl data; char *pathp = path; afs_uint32 blob[PIOCTL_HEADER]; *errornumber = 0; SETCLIENTCONTEXT(blob, rx_HostOf(call->conn->peer), creds->uid, creds->group0, creds->group1, cmd, NFS_EXPORTER); data.in = (char *)malloc(InData->rmtbulk_len + PIOCTL_HEADER * sizeof(afs_int32)); if (!data.in) return (-1); /* helpless here */ if (!strcmp(path, NIL_PATHP)) pathp = (char *)0; /* It meant to be NIL */ memcpy(data.in, blob, sizeof(blob)); inparam_conversion(cmd, InData->rmtbulk_val, 1); memcpy(data.in + sizeof(blob), InData->rmtbulk_val, InData->rmtbulk_len); data.in_size = InData->rmtbulk_len + PIOCTL_HEADER * sizeof(afs_int32); data.out = OutData->rmtbulk_val; data.out_size = OutData->rmtbulk_len; /* force local pioctl call */ error = lpioctl(pathp, _VICEIOCTL(PSetClientContext), &data, follow); if (error) { *errornumber = errno; } else { /* Send the results back in network order */ outparam_conversion(cmd, data.out, 0); } free(data.in); /* Note that we return success (i.e. 0) even when pioctl fails; that's * because the actual errno is passed back via 'errornumber' and this call * MUST return success error in order to get that OUT params back (YUCK!) */ return (0); }
static int SetSysname(afs_int32 ahost, afs_int32 auid, char *sysname) { afs_int32 code; afs_int32 pheader[6]; char space[1200], *tp; struct ViceIoctl blob; afs_int32 setp = 1; /* otherwise we've got the token, now prepare to build the pioctl args */ pheader[0] = ahost; pheader[1] = auid; pheader[2] = 0; /* group low */ pheader[3] = 0; /* group high */ pheader[4] = 38 /*VIOC_AFS_SYSNAME */ ; /* sysname pioctl index */ pheader[5] = 1; /* NFS protocol exporter # */ /* copy stuff in */ memcpy(space, pheader, sizeof(pheader)); tp = space + sizeof(pheader); /* finally setup the pioctl call's parameters */ blob.in_size = sizeof(pheader); blob.in = space; blob.out_size = 0; blob.out = NULL; memcpy(tp, &setp, sizeof(afs_int32)); tp += sizeof(afs_int32); strcpy(tp, sysname); blob.in_size += sizeof(afs_int32) + strlen(sysname) + 1; tp += strlen(sysname); *(tp++) = '\0'; code = pioctl(NULL, _VICEIOCTL(99), &blob, 0); if (code) { code = errno; } return code; }
/* * Copy * This does the bulk of the work of the program. Handle one file, * possibly copying subfiles if this is a directory */ static int Copy(char *file1, char *file2, short recursive, int level) { struct stat s1, s2; /*Stat blocks */ struct ViceIoctl blob; char aclspace[MAXACL]; afs_int32 rcode = 0, code; int goods2 = 1; code = lstat(file1, &s1); if (code < 0) { fprintf(stderr, "Can't find %s\n", file1); return 1; } code = lstat(file2, &s2); if (code < 0) { if (!MakeParent(file2, s1.st_uid)) return 0; goods2 = 0; } if ((s1.st_mode & S_IFMT) == S_IFREG) { /* * -------------------- Copy regular file -------------------- */ int f1, f2, n; char buf[4096]; /* Must be bigger than sizeof (*head) */ struct timeval tv[2]; char tmpfile[MAXPATHLEN], newName[MAXPATHLEN]; if (verbose) { printf("Level %d: File %s to %s\n", level, file1, file2); fflush(stdout); } /* Wonder if there is a security hole */ if (((s1.st_mode & 04002) == 04002) || ((s1.st_mode & 04020) == 04020) || ((s1.st_mode & 02002) == 02002)) { fprintf(stderr, "WARNING: Mode-bits security hole in files %s and %s\n", file1, file2); } if (!goods2 || (s1.st_mtime != s2.st_mtime) || (s1.st_size != s2.st_size)) { /*c */ /* Don't ovewrite a write protected file (unless force: -f) */ if (!forceOverwrite && goods2 && (s2.st_mode & 0200) == 0) { fprintf(stderr, "File %s is write protected against its owner; not changed\n", file2); return 1; } if (verbose) { printf(" Copy file %s to %s (%u Bytes)\n", file1, file2, (unsigned int) s1.st_size); fflush(stdout); } strlcpy(tmpfile, file2, sizeof tmpfile); /* Name of temporary file */ strlcat(tmpfile, ".UPD", sizeof tmpfile); /* open file1 for input */ f1 = open(file1, O_RDONLY); if (f1 < 0) { fprintf(stderr, "Unable to open input file %s: %s\n", file1, strerror(errno)); return 1; } /* open temporary output file */ f2 = open(tmpfile, (O_WRONLY | O_CREAT | O_TRUNC), s1.st_mode); if (f2 < 0) { fprintf(stderr, "Unable to open output file %s: %s\n", tmpfile, strerror(errno)); fflush(stdout); close(f1); return 1; } /* Copy file1 to temporary file */ while ((n = read(f1, buf, sizeof(buf))) > 0) { if (write(f2, buf, n) != n) { fprintf(stderr, "Write failed, file %s must be copied again.\n", file2); } } /* preserve access and modification times: ("-x" disables) */ if (preserveDate) { tv[0].tv_sec = s1.st_atime; tv[0].tv_usec = 0; tv[1].tv_sec = s1.st_mtime; tv[1].tv_usec = 0; utimes(tmpfile, tv); } /* Close the files */ code = close(f1); code = close(f2); if (code < 0) { perror("close "); rcode = 1; } /* Rename file2 to file2.old. [-r] */ if (renameTargets && goods2) { strlcpy(newName, file2, sizeof newName); strlcat(newName, ".old", sizeof newName); if (verbose) { printf(" Renaming %s to %s\n", file2, newName); fflush(stdout); } if (rename(file2, newName) < 0) { fprintf(stderr, "Rename of %s to %s failed.\n", file2, newName); } } /* Rename temporary file to file2 */ code = rename(tmpfile, file2); if (code < 0) { fprintf(stderr, "Rename of %s to %s failed.\n", tmpfile, file2); return 1; } /* Re-stat file2 and compare file sizes */ code = lstat(file2, &s2); if (code < 0) { fprintf(stderr, "WARNING: Unable to stat new file %s\n", file2); return 1; } if (s1.st_size != s2.st_size) { fprintf(stderr, "WARNING: New file %s is %u bytes long; should be %u\n", file2, (unsigned int) s2.st_size, (unsigned int) s1.st_size); } } /*c */ /* Set the user-id */ if (s2.st_uid != s1.st_uid) { if (verbose) { printf(" Set owner-id for %s to %d\n", file2, s1.st_uid); fflush(stdout); } code = chown(file2, s1.st_uid, -1); if (code) { fprintf(stderr, "Unable to set owner-id for %s to %d\n", file2, s1.st_uid); fflush(stdout); rcode = 1; s1.st_mode &= ~04000; /* Don't set suid bit */ } } /* Set the group-id */ if (s2.st_gid != s1.st_gid) { if (verbose) { printf(" Set group-id for %s to %d\n", file2, s1.st_gid); fflush(stdout); } code = chown(file2, -1, s1.st_gid); if (code) { fprintf(stderr, "Unable to set group-id for %s to %d\n", file2, s1.st_gid); fflush(stdout); rcode = 1; s1.st_mode &= ~02000; /* Don't set sgid bit */ } } /* Set the mode bits */ if (s1.st_mode != s2.st_mode) { if (verbose) { printf(" Set mode-bit for %s to %o\n", file2, (s1.st_mode & 07777)); fflush(stdout); } code = chmod(file2, s1.st_mode); if (code) { fprintf(stderr, "Unable to set mode-bits for %s to %d\n", file2, s1.st_mode); rcode = 1; } } } /* regular file */ else if ((s1.st_mode & S_IFMT) == S_IFLNK) { /* * --------------------- Copy symlink -------------------- */ char linkvalue[MAXPATHLEN + 1]; int n; if (verbose) { printf("Level %d: Symbolic link %s to %s\n", level, file1, file2); fflush(stdout); } /* Don't ovewrite a write protected directory (unless force: -f) */ if (!forceOverwrite && goods2 && (s2.st_mode & 0200) == 0) { fprintf(stderr, "Link %s is write protected against its owner; not changed\n", file2); return 1; } if (verbose) { printf(" Copy symbolic link %s->%s to %s\n", file1, linkvalue, file2); fflush(stdout); } n = readlink(file1, linkvalue, sizeof(linkvalue)); if (n == -1) { fprintf(stderr, "Could not read symbolic link %s\n", file1); perror("read link "); return 1; } linkvalue[n] = 0; unlink(file2); /* Always make the new link (it was easier) */ code = symlink(linkvalue, file2); if (code == -1) { fprintf(stderr, "Could not create symbolic link %s\n", file2); perror("create link "); return 1; } } /*Dealing with symlink */ else if (preserveMountPoints && (code = isMountPoint(file1, &blob))) { /* * --------------------- Copy mount point -------------------- */ if (code > 1) { perror("checking for mount point "); return 1; } if (verbose) { printf("Level %d: Mount point %s to %s\n", level, file1, file2); fflush(stdout); } /* Don't ovewrite a write protected directory (unless force: -f) */ if (!forceOverwrite && goods2 && (s2.st_mode & 0200) == 0) { fprintf(stderr, "Target %s is write protected against its owner; not changed\n", file2); return 1; } if (verbose) { printf(" Copy mount point %s for vol %s to %s\n", file1, blob.out, file2); fflush(stdout); } unlink(file2); /* Always make the new link (it was easier) */ strcat(blob.out, "."); /* stupid convention; these end with a period */ code = symlink(blob.out, file2); if (code == -1) { fprintf(stderr, "Could not create mount point %s for vol %s\n", file2, blob.out); perror("create mount point "); return 1; } } /*Dealing with mount point */ else if (((s1.st_mode & S_IFMT) == S_IFDIR) && (recursive || (level == 0))) { /* * ----------------------- Copy directory ----------------------- */ DIR *dir; int tfd, code, i; struct OldAcl *oacl; char tacl[MAXACL]; char f1[MAXPATHLEN], f2[MAXPATHLEN]; char *p1, *p2; struct dirent *d; struct timeval tv[2]; if (verbose) { printf("Level %d: Directory %s to %s\n", level, file1, file2); fflush(stdout); } /* Don't ovewrite a write protected directory (unless force: -f) */ if (!forceOverwrite && goods2 && (s2.st_mode & 0200) == 0) { fprintf(stderr, "Directory %s is write protected against its owner; not changed\n", file2); return 1; } strlcpy(f1, file1, sizeof f1); strlcpy(f2, file2, sizeof f2); p1 = f1 + strlen(f1); p2 = f2 + strlen(f2); if (p1 == f1 || p1[-1] != '/') *p1++ = '/'; if (p2 == f2 || p2[-1] != '/') *p2++ = '/'; dir = opendir(file1); if (dir == NULL) { fprintf(stderr, "Couldn't open %s\n", file1); return 1; } while ((d = readdir(dir)) != NULL) { if (strcmp(d->d_name, ".") == 0 || strcmp(d->d_name, "..") == 0) continue; strlcpy(p1, d->d_name, sizeof f1 - (p1 - f1)); strlcpy(p2, d->d_name, sizeof f2 - (p2 - f2)); code = Copy(f1, f2, recursive, level + 1); if (code && !rcode) rcode = 1; /* remember errors */ } closedir(dir); if (verbose) { printf("Level %d: Copied directory %s to %s\n", level, file1, file2); fflush(stdout); } mkdir(file2, 0777); /* Handle case where MakeParent not invoked. */ if (verbose) { printf(" Set owner-id for %s to %d\n", file2, s1.st_uid); fflush(stdout); } code = chown(file2, s1.st_uid, -1); if (code) { fprintf(stderr, "Unable to set owner-id for %s to %d\n", file2, s1.st_uid); fflush(stdout); s1.st_mode &= ~04000; /* Don't set suid bit */ } if (verbose) { printf(" Set group-id for %s to %d\n", file2, s1.st_gid); fflush(stdout); } code = chown(file2, -1, s1.st_gid); if (code) { fprintf(stderr, "Unable to set group-id for %s to %d\n", file2, s1.st_gid); fflush(stdout); s1.st_mode &= ~02000; /* Don't set sgid bit */ } if (verbose) { printf(" Set mode-bit for %s to %o\n", file2, (s1.st_mode & 07777)); fflush(stdout); } code = chmod(file2, s1.st_mode); if (code) { fprintf(stderr, "Unable to set mode-bits for %s to %d\n", file2, s1.st_mode); fflush(stdout); rcode = 1; } if (setacl == 1) { if (verbose) { printf(" Set acls for %s\n", file2); fflush(stdout); } blob.in = aclspace; blob.out = aclspace; blob.in_size = 0; blob.out_size = MAXACL; if (oldAcl) { /* Get an old-style ACL and convert it */ if (verbose) { printf(" Getting old style acl\n"); fflush(stdout); } for (i = 1; i < strlen(file1); i++) if (file1[i] == '/') break; strlcpy(aclspace, &file1[i], sizeof aclspace); blob.in_size = 1 + strlen(aclspace); tfd = open(file1, O_RDONLY, 0); if (tfd < 0) { perror("old-acl open "); return 1; } code = ioctl(tfd, _VICEIOCTL(4), &blob); close(tfd); if (code < 0) { if (errno == EINVAL) { setacl = 0; if (verbose) { printf(" _VICEIOCTL(4) returns EINVAL\n"); fflush(stdout); } } else { return 1; } } /* Now convert the thing. */ oacl = (struct OldAcl *)(aclspace + 4); sprintf(tacl, "%d\n%d\n", oacl->nplus, oacl->nminus); strlcat(tacl, oacl->data, sizeof tacl); strlcpy(aclspace, tacl, sizeof aclspace); } /*Grab and convert old-style ACL */ else { /* Get a new-style ACL */ if (verbose) { printf(" Getting new style acl\n"); fflush(stdout); } code = pioctl(file1, _VICEIOCTL(2), &blob, 1); if (code < 0) { if (errno == EINVAL) { setacl = 0; if (verbose) { printf(" _VICEIOCTL(2) returns EINVAL\n"); fflush(stdout); } } else { perror("getacl "); return 1; } } } /*Grab new-style ACL */ /* * Now, set the new-style ACL. */ if (setacl == 1) { if (verbose) { printf(" Setting new style acl\n"); fflush(stdout); } blob.out = aclspace; blob.in = aclspace; blob.out_size = 0; blob.in_size = 1 + strlen(aclspace); code = pioctl(file2, _VICEIOCTL(1), &blob, 1); if (code) { if (errno == EINVAL) { setacl = 0; if (verbose) { printf(" _VICEIOCTL(1) returns EINVAL\n"); fflush(stdout); } } else { fprintf(stderr, "Couldn't set acls for %s\n", file2); return 1; } } } if (setacl == 0) { printf("Not setting acls\n"); } } /* preserve access and modification times: ("-x" disables) */ if (preserveDate) { tv[0].tv_sec = s1.st_atime; tv[0].tv_usec = 0; tv[1].tv_sec = s1.st_mtime; tv[1].tv_usec = 0; utimes(file2, tv); } } return rcode; } /*Copy */
static int GetTokens(afs_int32 ahost, afs_int32 auid) { struct ViceIoctl iob; afs_int32 pheader[6]; char tbuffer[1024]; afs_int32 code = 0; int index, newIndex; char *stp; /* secret token ptr */ struct ClearToken ct; char *tp; afs_int32 temp, gotit = 0; int maxLen; /* biggest ticket we can copy */ int tktLen; /* server ticket length */ time_t tokenExpireTime; char UserName[MAXKTCNAMELEN + MAXKTCNAMELEN]; struct ktc_token token; struct ktc_principal clientName; time_t current_time; char *expireString; current_time = time(0); /* otherwise we've got the token, now prepare to build the pioctl args */ pheader[0] = ahost; pheader[1] = auid; pheader[2] = 0; /* group low */ pheader[3] = 0; /* group high */ pheader[4] = 8; /* gettoken pioctl index */ pheader[5] = 1; /* NFS protocol exporter # */ for (index = 0; index < 200; index++) { /* sanity check in case pioctl fails */ code = ktc_ListTokens(index, &newIndex, &clientName); if (code) { if (code == KTC_NOENT) { /* all done */ if (!gotit) printf("knfs: there are no tokens here.\n"); code = 0; } break; /* done, but failed */ } if (strcmp(clientName.name, "afs") != 0) continue; /* wrong ticket service */ /* copy stuff in */ memcpy(tbuffer, pheader, sizeof(pheader)); tp = tbuffer + sizeof(pheader); memcpy(tp, &index, sizeof(afs_int32)); tp += sizeof(afs_int32); iob.in = tbuffer; iob.in_size = sizeof(afs_int32) + sizeof(pheader); iob.out = tbuffer; iob.out_size = sizeof(tbuffer); code = pioctl(NULL, _VICEIOCTL(99), &iob, 0); if (code < 0 && errno == EDOM) return KTC_NOENT; else if (code == 0) { /* check to see if this is the right cell/realm */ tp = tbuffer; memcpy(&temp, tp, sizeof(afs_int32)); /* get size of secret token */ tktLen = temp; /* remember size of ticket */ tp += sizeof(afs_int32); stp = tp; /* remember where ticket is, for later */ tp += temp; /* skip ticket for now */ memcpy(&temp, tp, sizeof(afs_int32)); /* get size of clear token */ if (temp != sizeof(struct ClearToken)) return KTC_ERROR; tp += sizeof(afs_int32); /* skip length */ memcpy(&ct, tp, temp); /* copy token for later use */ tp += temp; /* skip clear token itself */ tp += sizeof(afs_int32); /* skip primary flag */ /* tp now points to the cell name */ if (strcmp(tp, clientName.cell) == 0) { /* closing in now, we've got the right cell */ gotit = 1; maxLen = sizeof(token) - sizeof(struct ktc_token) + MAXKTCTICKETLEN; if (maxLen < tktLen) return KTC_TOOBIG; memcpy(token.ticket, stp, tktLen); token.startTime = ct.BeginTimestamp; token.endTime = ct.EndTimestamp; if (ct.AuthHandle == -1) ct.AuthHandle = 999; token.kvno = ct.AuthHandle; memcpy(&token.sessionKey, ct.HandShakeKey, sizeof(struct ktc_encryptionKey)); token.ticketLen = tktLen; if ((token.kvno == 999) || /* old style bcrypt ticket */ (ct.BeginTimestamp && /* new w/ prserver lookup */ (((ct.EndTimestamp - ct.BeginTimestamp) & 1) == 1))) { sprintf(clientName.name, "AFS ID %d", ct.ViceId); clientName.instance[0] = 0; } else { sprintf(clientName.name, "Unix UID %d", ct.ViceId); clientName.instance[0] = 0; } strlcpy(clientName.cell, tp, sizeof(clientName.cell)); tokenExpireTime = token.endTime; strlcpy(UserName, clientName.name, sizeof(UserName)); if (clientName.instance[0] != 0) { strlcat(UserName, ".", sizeof(UserName)); strlcat(UserName, clientName.instance, sizeof(UserName)); } if (UserName[0] == 0) printf("Tokens"); else if (strncmp(UserName, "AFS ID", 6) == 0) { printf("User's (%s) tokens", UserName); } else if (strncmp(UserName, "Unix UID", 8) == 0) { printf("Tokens"); } else printf("User %s's tokens", UserName); printf(" for %s%s%s@%s ", clientName.name, clientName.instance[0] ? "." : "", clientName.instance, clientName.cell); if (tokenExpireTime <= current_time) printf("[>> Expired <<]\n"); else { expireString = ctime(&tokenExpireTime); expireString += 4; /*Move past the day of week */ expireString[12] = '\0'; printf("[Expires %s]\n", expireString); } } } } return code; }
/* Copy the AFS service token into the kernel for a particular host and user */ static int NFSCopyToken(afs_int32 ahost, afs_int32 auid) { struct ktc_principal client, server; struct ktc_token theTicket; afs_int32 code; afs_int32 pheader[6]; char space[1200]; struct ClearToken ct; afs_int32 index, newIndex; afs_int32 temp; /* for bcopy */ char *tp; struct ViceIoctl blob; for (index = 0;; index = newIndex) { code = ktc_ListTokens(index, &newIndex, &server); if (code) { if (code == KTC_NOENT) { /* all done */ code = 0; } break; /* done, but failed */ } if (strcmp(server.name, "afs") != 0) continue; /* wrong ticket service */ code = ktc_GetToken(&server, &theTicket, sizeof(theTicket), &client); if (code) return code; /* otherwise we've got the token, now prepare to build the pioctl args */ pheader[0] = ahost; pheader[1] = auid; pheader[2] = 0; /* group low */ pheader[3] = 0; /* group high */ pheader[4] = 3; /* set token pioctl index */ pheader[5] = 1; /* NFS protocol exporter # */ /* copy in the header */ memcpy(space, pheader, sizeof(pheader)); tp = space + sizeof(pheader); /* copy in the size of the encrypted part */ memcpy(tp, &theTicket.ticketLen, sizeof(afs_int32)); tp += sizeof(afs_int32); /* copy in the ticket itself */ memcpy(tp, theTicket.ticket, theTicket.ticketLen); tp += theTicket.ticketLen; /* copy in "clear token"'s size */ temp = sizeof(struct ClearToken); memcpy(tp, &temp, sizeof(afs_int32)); tp += sizeof(afs_int32); /* create the clear token and copy *it* in */ ct.AuthHandle = theTicket.kvno; /* where we hide the key version # */ memcpy(ct.HandShakeKey, &theTicket.sessionKey, sizeof(ct.HandShakeKey)); ct.ViceId = auid; ct.BeginTimestamp = theTicket.startTime; ct.EndTimestamp = theTicket.endTime; memcpy(tp, &ct, sizeof(ct)); tp += sizeof(ct); /* copy in obsolete primary flag */ temp = 0; memcpy(tp, &temp, sizeof(afs_int32)); tp += sizeof(afs_int32); /* copy in cell name, null terminated */ strcpy(tp, server.cell); tp += strlen(server.cell) + 1; /* finally setup the pioctl call's parameters */ blob.in_size = tp - space; blob.in = space; blob.out_size = 0; blob.out = NULL; code = pioctl(NULL, _VICEIOCTL(99), &blob, 0); if (code) { code = errno; break; } } return code; }