/* * Copyright 2000, International Business Machines Corporation and others. * All Rights Reserved. * * This software has been released under the terms of the IBM Public * License. For details, see the LICENSE file in the top-level source * directory or online at http://www.openafs.org/dl/license10.html */ /* unlog -- Tell the Andrew Cache Manager to either clean up your connection completely or eliminate the caller's PAG. February 1986 Usage: unlog [cell ...] where: cell is the name the pertinent cell. If no cell is provided, unlog destroys all tokens. If a cell, for which a token is not held, is provided it is ignored. */ #define VIRTUE 1 #define VICE 1 #include #include #include #include #include #include #include #include #include #undef VIRTUE #undef VICE struct tokenInfo { struct ktc_token token; struct ktc_principal service; struct ktc_principal client; int deleted; }; static int unlog_ForgetCertainTokens(char **, int); static int unlog_NormalizeCellNames(char **, int); static int unlog_CheckUnlogList(char **, int, struct ktc_principal *); static int unlog_VerifyUnlog(char **, int, struct tokenInfo *, int); static int CommandProc(struct cmd_syndesc *as, void *arock) { #define MAXCELLS 20 /* XXX */ struct cmd_item *itp; afs_int32 code, i = 0; char *cells[20]; if (as->parms[0].items) { /* A cell is provided */ for (itp = as->parms[0].items; itp; itp = itp->next) { if (i > MAXCELLS) { printf ("The maximum number of cells (%d) is exceeded; the rest are ignored\n", MAXCELLS); break; } cells[i++] = itp->data; } code = unlog_ForgetCertainTokens(cells, i); } else code = ktc_ForgetAllTokens(); if (code) { printf("unlog: could not discard tickets, code %d\n", code); exit(1); } return 0; } #include "AFS_component_version_number.c" int main(int argc, char *argv[]) { /*Main routine */ struct cmd_syndesc *ts; afs_int32 code; #ifdef AFS_AIX32_ENV /* * The following signal action for AIX is necessary so that in case of a * crash (i.e. core is generated) we can include the user's data section * in the core dump. Unfortunately, by default, only a partial core is * generated which, in many cases, isn't too useful. */ struct sigaction nsa; sigemptyset(&nsa.sa_mask); nsa.sa_handler = SIG_DFL; nsa.sa_flags = SA_FULLDUMP; sigaction(SIGSEGV, &nsa, NULL); #endif ts = cmd_CreateSyntax(NULL, CommandProc, NULL, "Release Kerberos authentication"); cmd_AddParm(ts, "-cell", CMD_LIST, CMD_OPTIONAL, "cell name"); code = cmd_Dispatch(argc, argv); exit(code != 0); } /*Main routine */ /* * Problem: only the KTC gives you the ability to selectively destroy * a specified token. * * Solution: Build a list of tokens, delete the bad ones (the ones to * remove from the permissions list,) destroy all tokens, and * then re-register the good ones. Ugly, but it works. */ static int unlog_ForgetCertainTokens(char **list, int listSize) { int index, index2; int count; afs_int32 code; struct ktc_principal serviceName; struct tokenInfo *tokenInfoP; /* normalize all the names in the list */ unlog_NormalizeCellNames(list, listSize); /* figure out how many tokens exist */ count = 0; do { code = ktc_ListTokens(count, &count, &serviceName); } while (!code); tokenInfoP = malloc((sizeof(struct tokenInfo) * count)); if (!tokenInfoP) { perror("unlog_ForgetCertainTokens -- osi_Alloc failed"); exit(1); } for (code = index = index2 = 0; (!code) && (index < count); index++) { code = ktc_ListTokens(index2, &index2, &(tokenInfoP + index)->service); if (!code) { code = ktc_GetToken(&(tokenInfoP + index)->service, &(tokenInfoP + index)->token, sizeof(struct ktc_token), &(tokenInfoP + index)->client); if (!code) (tokenInfoP + index)->deleted = unlog_CheckUnlogList(list, listSize, &(tokenInfoP + index)->client); } } unlog_VerifyUnlog(list, listSize, tokenInfoP, count); code = ktc_ForgetAllTokens(); if (code) { printf("unlog: could not discard tickets, code %d\n", code); exit(1); } for (code = index = 0; index < count; index++) { if (!((tokenInfoP + index)->deleted)) { code = ktc_SetToken(&(tokenInfoP + index)->service, &(tokenInfoP + index)->token, &(tokenInfoP + index)->client, 0); if (code) { fprintf(stderr, "Couldn't re-register token, code = %d\n", code); } } } return 0; } /* * 0 if not in list, 1 if in list */ int unlog_CheckUnlogList(char **list, int count, struct ktc_principal *principal) { do { if (strcmp(*list, principal->cell) == 0) return 1; list++; --count; } while (count); return 0; } /* * Caveat: this routine does NOT free up the memory passed (and replaced). * because it assumes it isn't a problem. */ int unlog_NormalizeCellNames(char **list, int size) { char *newCellName; unsigned index; struct afsconf_dir *conf; int code; struct afsconf_cell cellinfo; if (!(conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) { fprintf(stderr, "Cannot get cell configuration info!\n"); exit(1); } for (index = 0; index < size; index++, list++) { newCellName = malloc(MAXKTCREALMLEN); if (!newCellName) { perror("unlog_NormalizeCellNames --- malloc failed"); exit(1); } lcstring(newCellName, *list, MAXKTCREALMLEN); code = afsconf_GetCellInfo(conf, newCellName, 0, &cellinfo); if (code) { if (code == AFSCONF_NOTFOUND) { fprintf(stderr, "Unrecognized cell name %s\n", newCellName); } else { fprintf(stderr, "unlog_NormalizeCellNames - afsconf_GetCellInfo"); fprintf(stderr, " failed, code = %d\n", code); } exit(1); } strcpy(newCellName, cellinfo.name); *list = newCellName; } afsconf_Close(conf); return 0; } /* * check given list to assure tokens were held for specified cells * prints warning messages for those cells without such entries. */ int unlog_VerifyUnlog(char **cellList, int cellListSize, struct tokenInfo *tokenList, int tokenListSize) { int index; for (index = 0; index < cellListSize; index++) { int index2; int found; for (found = index2 = 0; !found && index2 < tokenListSize; index2++) found = strcmp(cellList[index], (tokenList + index2)->client.cell) == 0; if (!found) fprintf(stderr, "unlog: Warning - no tokens held for cell %s\n", cellList[index]); } return 0; }