OPENAFS-SA-2018-002 butc: prevent TC_DumpStatus, TC_ScanStatus information leaks
[openafs.git] / src / butc / tcstatus.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 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 #include <afs/com_err.h>
16 #include <lock.h>
17 #include <afs/bubasics.h>
18 #include <afs/tcdata.h>
19 #include <afs/butc.h>
20 #include <afs/budb_client.h>
21 #include <afs/bucoord_prototypes.h>
22
23 #include "butc_internal.h"
24 #include "error_macros.h"
25 #include "butc_xbsa.h"
26
27 /* tape coordinator - task status management */
28 extern afs_int32 xbsaType;
29
30 dlqlinkT statusHead;
31 struct Lock statusQueueLock;
32 struct Lock cmdLineLock;
33
34 /* STC_GetStatus
35  *      get the status of a task
36  * entry:
37  *      taskId - task for which status required
38  * exit:
39  *      statusPtr - filled in with task status
40  */
41
42 afs_int32
43 STC_GetStatus(struct rx_call *call, afs_uint32 taskId,
44               struct tciStatusS *statusPtr)
45 {
46     statusP ptr;
47     int retval = 0;
48
49     memset(statusPtr, 0, sizeof(*statusPtr));
50     if (callPermitted(call) == 0)
51         return (TC_NOTPERMITTED);
52
53     lock_Status();
54     ptr = findStatus(taskId);
55     if (ptr) {
56         strcpy(statusPtr->taskName, ptr->taskName);
57         strcpy(statusPtr->volumeName, ptr->volumeName);
58         statusPtr->taskId = ptr->taskId;
59         statusPtr->flags = ptr->flags;
60         statusPtr->nKBytes = ptr->nKBytes;
61         statusPtr->dbDumpId = ptr->dbDumpId;
62         statusPtr->lastPolled = ptr->lastPolled;
63         statusPtr->volsFailed = ptr->volsFailed;
64         ptr->lastPolled = time(0);
65     } else
66         retval = TC_NODENOTFOUND;
67     unlock_Status();
68
69     return (retval);
70 }
71
72 afs_int32
73 STC_EndStatus(struct rx_call *call, afs_uint32 taskId)
74 {
75     statusP ptr;
76     int retval = 0;
77
78     if (callPermitted(call) == 0)
79         return (TC_NOTPERMITTED);
80
81     lock_Status();
82     ptr = findStatus(taskId);
83     unlock_Status();
84
85     if (ptr)
86         deleteStatusNode(ptr);
87     else
88         retval = TC_NODENOTFOUND;
89
90     return (retval);
91 }
92
93 afs_int32
94 STC_RequestAbort(struct rx_call *call, afs_uint32 taskId)
95 {
96     statusP ptr;
97     int retval = 0;
98
99     if (callPermitted(call) == 0)
100         return (TC_NOTPERMITTED);
101
102     lock_Status();
103     ptr = findStatus(taskId);
104     if (ptr)
105         ptr->flags |= ABORT_REQUEST;
106     else
107         retval = TC_NODENOTFOUND;
108     unlock_Status();
109     return (retval);
110 }
111
112 /* STC_ScanStatus
113  *      Get status of all tasks on the butc, successively. Initial call
114  *      should come in with TSK_STAT_FIRST flag set to initialize the
115  *      scan.
116  * entry:
117  *      taskId - specifies the task whose status is to be returned
118  *              (unless TSK_STAT_FIRST set in which case it is ignored)
119  * exit:
120  *      taskId - id of next task in the list
121  *      flags - TSK_STAT_END will be set when one reaches the end of
122  *              the task list. taskId is not updated in this case.
123  * return values:
124  *      0 - normal
125  *      TC_NOTASKS - no tasks active
126  */
127
128 afs_int32
129 STC_ScanStatus(struct rx_call *call, afs_uint32 *taskId,
130                struct tciStatusS *statusPtr, afs_uint32 *flags)
131 {
132     statusP ptr = 0;
133     dlqlinkP dlqPtr;
134
135     memset(statusPtr, 0, sizeof(*statusPtr));
136     if (callPermitted(call) == 0)
137         return (TC_NOTPERMITTED);
138
139     lock_Status();
140
141     if (CONF_XBSA)
142         *flags |= TSK_STAT_XBSA;
143     if (xbsaType == XBSA_SERVER_TYPE_ADSM)
144         *flags |= TSK_STAT_ADSM;
145
146     if (*flags & TSK_STAT_FIRST) {
147         /* find first status node */
148         dlqPtr = statusHead.dlq_next;
149         if (dlqPtr == &statusHead) {
150             /* no status nodes */
151             *flags |= (TSK_STAT_NOTFOUND | TSK_STAT_END);
152             unlock_Status();
153             return (0);
154         }
155         ptr = (statusP) dlqPtr;
156     } else {
157         ptr = findStatus(*taskId);
158         if (ptr == 0) {
159             /* in the event that the set of tasks has changed, just
160              * finish, letting the caller retry
161              */
162
163             *flags |= (TSK_STAT_NOTFOUND | TSK_STAT_END);
164             unlock_Status();
165             return (0);
166         }
167     }
168
169     /* ptr is now set to the status node we wish to return. Determine
170      * what the next node will be
171      */
172
173     if (ptr->link.dlq_next == &statusHead)
174         *flags |= TSK_STAT_END;
175     else
176         *taskId = ((statusP) ptr->link.dlq_next)->taskId;
177
178     strcpy(statusPtr->taskName, ptr->taskName);
179     strcpy(statusPtr->volumeName, ptr->volumeName);
180     statusPtr->taskId = ptr->taskId;
181     statusPtr->flags = ptr->flags;
182     statusPtr->nKBytes = ptr->nKBytes;
183     statusPtr->lastPolled = ptr->lastPolled;
184
185     unlock_Status();
186     return (0);
187 }
188
189
190 /* ---------------------------------
191  * misc. status management routines
192  * ---------------------------------
193  */
194
195 /* checkAbortByTaskId
196  * exit:
197  *      0 - continue
198  *      n - abort requested
199  */
200
201 int
202 checkAbortByTaskId(afs_uint32 taskId)
203 {
204     statusP statusPtr;
205     int retval = 0;
206
207     lock_Status();
208     statusPtr = findStatus(taskId);
209     if (statusPtr) {
210         retval = statusPtr->flags & ABORT_REQUEST;
211     }
212     unlock_Status();
213     return (retval);
214 }
215
216 /* getStatusFlag
217  *      For backwards compatibility. Queries flag status
218  * exit:
219  *      0 - flag clear
220  *      n - flag set
221  */
222
223 afs_uint32
224 getStatusFlag(afs_uint32 taskId, afs_uint32 flag)
225 {
226     statusP statusPtr;
227     int retval = 0;
228
229     lock_Status();
230     statusPtr = findStatus(taskId);
231     if (statusPtr) {
232         retval = statusPtr->flags & flag;
233     }
234     unlock_Status();
235     return (retval);
236 }