Windows: permit offline volume check to be disabled
[openafs.git] / src / WINNT / afsd / cm_user.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 #include <afsconfig.h>
12 #include <afs/param.h>
13 #include <roken.h>
14
15 #include <afs/stds.h>
16
17 #include <windows.h>
18 #include <malloc.h>
19 #include <string.h>
20
21 #include "afsd.h"
22 #include "smb.h"
23 #include <osi.h>
24 #include <rx/rx.h>
25
26
27 osi_rwlock_t cm_userLock;
28
29 cm_user_t *cm_rootUserp;
30
31 void cm_InitUser(void)
32 {
33     static osi_once_t once;
34
35     if (osi_Once(&once)) {
36         lock_InitializeRWLock(&cm_userLock, "cm_userLock", LOCK_HIERARCHY_USER_GLOBAL);
37         osi_EndOnce(&once);
38     }
39
40     cm_rootUserp = cm_NewUser();
41 }
42
43 cm_user_t *cm_NewUser(void)
44 {
45     cm_user_t *userp;
46
47     userp = malloc(sizeof(*userp));
48     memset(userp, 0, sizeof(*userp));
49     userp->refCount = 1;
50     lock_InitializeMutex(&userp->mx, "cm_user_t", LOCK_HIERARCHY_USER);
51     return userp;
52 }
53
54 /* must be called with locked userp */
55 cm_ucell_t *cm_GetUCell(cm_user_t *userp, cm_cell_t *cellp)
56 {
57     cm_ucell_t *ucp;
58
59     lock_AssertMutex(&userp->mx);
60     for (ucp = userp->cellInfop; ucp; ucp=ucp->nextp) {
61         if (ucp->cellp == cellp)
62             break;
63     }
64
65     if (!ucp) {
66         ucp = malloc(sizeof(*ucp));
67         memset(ucp, 0, sizeof(*ucp));
68         ucp->nextp = userp->cellInfop;
69         if (userp->cellInfop)
70             ucp->iterator = userp->cellInfop->iterator + 1;
71         else
72             ucp->iterator = 1;
73         userp->cellInfop = ucp;
74         ucp->cellp = cellp;
75     }
76
77     return ucp;
78 }
79
80 cm_ucell_t *cm_FindUCell(cm_user_t *userp, int iterator)
81 {
82     cm_ucell_t *ucp;
83     cm_ucell_t *best;
84
85     best = NULL;
86     lock_AssertMutex(&userp->mx);
87     for (ucp = userp->cellInfop; ucp; ucp = ucp->nextp) {
88         if (ucp->iterator >= iterator)
89             best = ucp;
90         else
91             break;
92     }
93     return best;
94 }
95
96 void cm_HoldUser(cm_user_t *up)
97 {
98     lock_ObtainWrite(&cm_userLock);
99     up->refCount++;
100     lock_ReleaseWrite(&cm_userLock);
101 }
102
103 void cm_ReleaseUser(cm_user_t *userp)
104 {
105     cm_ucell_t *ucp;
106     cm_ucell_t *ncp;
107
108     if (userp == NULL)
109         return;
110
111     lock_ObtainWrite(&cm_userLock);
112     osi_assertx(userp->refCount-- > 0, "cm_user_t refCount 0");
113     if (userp->refCount == 0) {
114         lock_FinalizeMutex(&userp->mx);
115         for (ucp = userp->cellInfop; ucp; ucp = ncp) {
116             ncp = ucp->nextp;
117             if (ucp->ticketp)
118                 free(ucp->ticketp);
119             free(ucp);
120         }
121         free(userp);
122     }
123     lock_ReleaseWrite(&cm_userLock);
124 }
125
126
127 void cm_HoldUserVCRef(cm_user_t *userp)
128 {
129     lock_ObtainMutex(&userp->mx);
130     userp->vcRefs++;
131     lock_ReleaseMutex(&userp->mx);
132 }
133
134 /* release the count of the # of connections that use this user structure.
135  * When this hits zero, we know we won't be getting any new requests from
136  * this user, and thus we can start GC'ing connections.  Ref count on user
137  * won't hit zero until all cm_conn_t's have been GC'd, since they hold
138  * refCount references to userp.
139  */
140 void cm_ReleaseUserVCRef(cm_user_t *userp)
141 {
142     lock_ObtainMutex(&userp->mx);
143     osi_assertx(userp->vcRefs-- > 0, "cm_user_t refCount 0");
144     lock_ReleaseMutex(&userp->mx);
145 }
146
147
148 /*
149  * Check if any users' tokens have expired and if they have then do the
150  * equivalent of unlogging the user for that particular cell for which
151  * the tokens have expired.
152  * ref. cm_IoctlDelToken() in cm_ioctl.c
153  * This routine is called by the cm_Daemon() ie. the periodic daemon.
154  * every cm_daemonTokenCheckInterval seconds
155  */
156 void cm_CheckTokenCache(time_t now)
157 {
158     extern smb_vc_t *smb_allVCsp; /* global vcp list */
159     smb_vc_t   *vcp;
160     smb_user_t *usersp;
161     cm_user_t  *userp = NULL;
162     cm_ucell_t *ucellp;
163     BOOL bExpired=FALSE;
164
165     /*
166      * For every vcp, get the user and check his tokens
167      */
168     lock_ObtainRead(&smb_rctLock);
169     for (vcp=smb_allVCsp; vcp; vcp=vcp->nextp) {
170         for (usersp=vcp->usersp; usersp; usersp=usersp->nextp) {
171             if (usersp->unp) {
172                 if ((userp=usersp->unp->userp)==0)
173                     continue;
174             } else
175                 continue;
176             lock_ObtainMutex(&userp->mx);
177             for (ucellp=userp->cellInfop; ucellp; ucellp=ucellp->nextp) {
178                 if (ucellp->flags & CM_UCELLFLAG_RXKAD) {
179                     if (ucellp->expirationTime < now) {
180                         /* this guy's tokens have expired */
181                         osi_Log3(afsd_logp, "cm_CheckTokens: Tokens for user:%s have expired expiration time:0x%x ucellp:%x",
182                                  ucellp->userName, ucellp->expirationTime, ucellp);
183                         if (ucellp->ticketp) {
184                             free(ucellp->ticketp);
185                             ucellp->ticketp = NULL;
186                         }
187                         _InterlockedAnd(&ucellp->flags, ~CM_UCELLFLAG_RXKAD);
188                         ucellp->gen++;
189                         bExpired=TRUE;
190                     }
191                 }
192             }
193             lock_ReleaseMutex(&userp->mx);
194             if (bExpired) {
195                 bExpired=FALSE;
196                 cm_ResetACLCache(NULL, userp);
197             }
198         }
199     }
200     lock_ReleaseRead(&smb_rctLock);
201 }
202
203 #ifdef USE_ROOT_TOKENS
204 /*
205  * Service/Parameters/RootTokens/<cellname>/
206  * -> UseLSA
207  * -> Keytab (required if UseLSA is 0)
208  * -> Principal (required if there is more than one principal in the keytab)
209  * -> Realm (required if realm is not upper-case of <cellname>
210  * -> RequireEncryption
211  */
212
213 void
214 cm_RefreshRootTokens(void)
215 {
216
217 }
218 #endif