3542e7f242828f564d6b3a81cffe3e25d13132ce
[openafs.git] / src / log / unlog.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11         unlog -- Tell the Andrew Cache Manager to either clean up your connection completely
12                     or eliminate the caller's PAG.
13         February 1986
14
15        Usage:
16               unlog [cell ...]
17
18               where:
19                   cell is the name the pertinent cell.
20
21         If no cell is provided, unlog destroys all tokens.
22
23         If a cell, for which a token is not held, is provided it is ignored.
24 */
25
26 #define VIRTUE      1
27 #define VICE        1
28
29 #include <afsconfig.h>
30 #include <afs/param.h>
31
32
33 #include <stdio.h>
34 #ifdef  AFS_AIX32_ENV
35 #include <signal.h>
36 #endif
37
38 #include <string.h>
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <errno.h>
42 #include <sys/ioctl.h>
43 #include <afs/vice.h>
44 #include <sys/file.h>
45
46 #include <afs/auth.h>
47 #include <afs/cellconfig.h>
48 #include <afs/afsutil.h>
49 #include <afs/cmd.h>
50
51 #undef VIRTUE
52 #undef VICE
53
54
55 struct tokenInfo {
56     struct ktc_token token;
57     struct ktc_principal service;
58     struct ktc_principal client;
59     int deleted;
60 };
61
62 static int unlog_ForgetCertainTokens(char **, int);
63 static int unlog_NormalizeCellNames(char **, int);
64 static int unlog_CheckUnlogList(char **, int, struct ktc_principal *);
65 static int unlog_VerifyUnlog(char **, int, struct tokenInfo *, int);
66
67 static int
68 CommandProc(struct cmd_syndesc *as, void *arock)
69 {
70 #define MAXCELLS 20             /* XXX */
71     struct cmd_item *itp;
72     afs_int32 code, i = 0;
73     char *cells[20];
74
75     if (as->parms[0].items) {   /* A cell is provided */
76         for (itp = as->parms[0].items; itp; itp = itp->next) {
77             if (i > MAXCELLS) {
78                 printf
79                     ("The maximum number of cells (%d) is exceeded; the rest are ignored\n",
80                      MAXCELLS);
81                 break;
82             }
83             cells[i++] = itp->data;
84         }
85         code = unlog_ForgetCertainTokens(cells, i);
86     } else
87         code = ktc_ForgetAllTokens();
88     if (code) {
89         printf("unlog: could not discard tickets, code %d\n", code);
90         exit(1);
91     }
92     return 0;
93 }
94
95
96 #include "AFS_component_version_number.c"
97
98 int
99 main(int argc, char *argv[])
100 {                               /*Main routine */
101     struct cmd_syndesc *ts;
102     afs_int32 code;
103
104 #ifdef  AFS_AIX32_ENV
105     /*
106      * The following signal action for AIX is necessary so that in case of a
107      * crash (i.e. core is generated) we can include the user's data section
108      * in the core dump. Unfortunately, by default, only a partial core is
109      * generated which, in many cases, isn't too useful.
110      */
111     struct sigaction nsa;
112
113     sigemptyset(&nsa.sa_mask);
114     nsa.sa_handler = SIG_DFL;
115     nsa.sa_flags = SA_FULLDUMP;
116     sigaction(SIGSEGV, &nsa, NULL);
117 #endif
118
119     ts = cmd_CreateSyntax(NULL, CommandProc, NULL,
120                           "Release Kerberos authentication");
121     cmd_AddParm(ts, "-cell", CMD_LIST, CMD_OPTIONAL, "cell name");
122
123     code = cmd_Dispatch(argc, argv);
124     exit(code != 0);
125 }                               /*Main routine */
126
127
128 /*
129  * Problem: only the KTC gives you the ability to selectively destroy
130  *          a specified token.
131  *
132  * Solution: Build a list of tokens, delete the bad ones (the ones to
133  *           remove from the permissions list,) destroy all tokens, and
134  *           then re-register the good ones.  Ugly, but it works.
135  */
136
137 static int
138 unlog_ForgetCertainTokens(char **list, int listSize)
139 {
140     int index, index2;
141     int count;
142     afs_int32 code;
143     struct ktc_principal serviceName;
144     struct tokenInfo *tokenInfoP;
145
146     /* normalize all the names in the list */
147     unlog_NormalizeCellNames(list, listSize);
148
149     /* figure out how many tokens exist */
150     count = 0;
151     do {
152         code = ktc_ListTokens(count, &count, &serviceName);
153     } while (!code);
154
155     tokenInfoP =
156         (struct tokenInfo *)malloc((sizeof(struct tokenInfo) * count));
157     if (!tokenInfoP) {
158         perror("unlog_ForgetCertainTokens -- osi_Alloc failed");
159         exit(1);
160     }
161
162     for (code = index = index2 = 0; (!code) && (index < count); index++) {
163         code =
164             ktc_ListTokens(index2, &index2, &(tokenInfoP + index)->service);
165
166         if (!code) {
167             code =
168                 ktc_GetToken(&(tokenInfoP + index)->service,
169                              &(tokenInfoP + index)->token,
170                              sizeof(struct ktc_token),
171                              &(tokenInfoP + index)->client);
172
173             if (!code)
174                 (tokenInfoP + index)->deleted =
175                     unlog_CheckUnlogList(list, listSize,
176                                          &(tokenInfoP + index)->client);
177         }
178     }
179
180     unlog_VerifyUnlog(list, listSize, tokenInfoP, count);
181     code = ktc_ForgetAllTokens();
182
183     if (code) {
184         printf("unlog: could not discard tickets, code %d\n", code);
185         exit(1);
186     }
187
188     for (code = index = 0; index < count; index++) {
189         if (!((tokenInfoP + index)->deleted)) {
190             code =
191                 ktc_SetToken(&(tokenInfoP + index)->service,
192                              &(tokenInfoP + index)->token,
193                              &(tokenInfoP + index)->client, 0);
194             if (code) {
195                 fprintf(stderr, "Couldn't re-register token, code = %d\n",
196                         code);
197             }
198         }
199     }
200     return 0;
201 }
202
203 /*
204  * 0 if not in list, 1 if in list
205  */
206 int
207 unlog_CheckUnlogList(char **list, int count, struct ktc_principal *principal)
208 {
209     do {
210         if (strcmp(*list, principal->cell) == 0)
211             return 1;
212         list++;
213         --count;
214     } while (count);
215
216     return 0;
217 }
218
219 /*
220  * Caveat: this routine does NOT free up the memory passed (and replaced).
221  *         because it assumes it isn't a problem.
222  */
223
224 int
225 unlog_NormalizeCellNames(char **list, int size)
226 {
227     char *newCellName;
228     unsigned index;
229     struct afsconf_dir *conf;
230     int code;
231     struct afsconf_cell cellinfo;
232
233     if (!(conf = afsconf_Open(AFSDIR_CLIENT_ETC_DIRPATH))) {
234         fprintf(stderr, "Cannot get cell configuration info!\n");
235         exit(1);
236     }
237
238     for (index = 0; index < size; index++, list++) {
239         newCellName = malloc(MAXKTCREALMLEN);
240         if (!newCellName) {
241             perror("unlog_NormalizeCellNames --- malloc failed");
242             exit(1);
243         }
244
245         lcstring(newCellName, *list, MAXKTCREALMLEN);
246         code = afsconf_GetCellInfo(conf, newCellName, 0, &cellinfo);
247         if (code) {
248             if (code == AFSCONF_NOTFOUND) {
249                 fprintf(stderr, "Unrecognized cell name %s\n", newCellName);
250             } else {
251                 fprintf(stderr,
252                         "unlog_NormalizeCellNames - afsconf_GetCellInfo");
253                 fprintf(stderr, " failed, code = %d\n", code);
254             }
255             exit(1);
256         }
257
258
259         strcpy(newCellName, cellinfo.name);
260
261         *list = newCellName;
262     }
263     afsconf_Close(conf);
264     return 0;
265 }
266
267 /*
268  * check given list to assure tokens were held for specified cells
269  * prints warning messages for those cells without such entries.
270  */
271 int
272 unlog_VerifyUnlog(char **cellList, int cellListSize, struct tokenInfo *tokenList, int tokenListSize)
273 {
274     int index;
275
276     for (index = 0; index < cellListSize; index++) {
277         int index2;
278         int found;
279
280         for (found = index2 = 0; !found && index2 < tokenListSize; index2++)
281             found =
282                 strcmp(cellList[index],
283                        (tokenList + index2)->client.cell) == 0;
284
285         if (!found)
286             fprintf(stderr, "unlog: Warning - no tokens held for cell %s\n",
287                     cellList[index]);
288     }
289     return 0;
290 }