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