Windows: track cm_rootUser connections
[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         if (userp == cm_rootUserp)
76             ucp->flags |= CM_UCELLFLAG_ROOTUSER;
77     }
78
79     return ucp;
80 }
81
82 cm_ucell_t *cm_FindUCell(cm_user_t *userp, int iterator)
83 {
84     cm_ucell_t *ucp;
85     cm_ucell_t *best;
86
87     best = NULL;
88     lock_AssertMutex(&userp->mx);
89     for (ucp = userp->cellInfop; ucp; ucp = ucp->nextp) {
90         if (ucp->iterator >= iterator)
91             best = ucp;
92         else
93             break;
94     }
95     return best;
96 }
97
98 void cm_HoldUser(cm_user_t *up)
99 {
100     lock_ObtainWrite(&cm_userLock);
101     up->refCount++;
102     lock_ReleaseWrite(&cm_userLock);
103 }
104
105 void cm_ReleaseUser(cm_user_t *userp)
106 {
107     cm_ucell_t *ucp;
108     cm_ucell_t *ncp;
109
110     if (userp == NULL)
111         return;
112
113     lock_ObtainWrite(&cm_userLock);
114     osi_assertx(userp->refCount-- > 0, "cm_user_t refCount 0");
115     if (userp->refCount == 0) {
116         lock_FinalizeMutex(&userp->mx);
117         for (ucp = userp->cellInfop; ucp; ucp = ncp) {
118             ncp = ucp->nextp;
119             if (ucp->ticketp)
120                 free(ucp->ticketp);
121             free(ucp);
122         }
123         free(userp);
124     }
125     lock_ReleaseWrite(&cm_userLock);
126 }
127
128
129 void cm_HoldUserVCRef(cm_user_t *userp)
130 {
131     lock_ObtainMutex(&userp->mx);
132     userp->vcRefs++;
133     lock_ReleaseMutex(&userp->mx);
134 }
135
136 /* release the count of the # of connections that use this user structure.
137  * When this hits zero, we know we won't be getting any new requests from
138  * this user, and thus we can start GC'ing connections.  Ref count on user
139  * won't hit zero until all cm_conn_t's have been GC'd, since they hold
140  * refCount references to userp.
141  */
142 void cm_ReleaseUserVCRef(cm_user_t *userp)
143 {
144     lock_ObtainMutex(&userp->mx);
145     osi_assertx(userp->vcRefs-- > 0, "cm_user_t refCount 0");
146     lock_ReleaseMutex(&userp->mx);
147 }
148
149
150 /*
151  * Check if any users' tokens have expired and if they have then do the
152  * equivalent of unlogging the user for that particular cell for which
153  * the tokens have expired.
154  * ref. cm_IoctlDelToken() in cm_ioctl.c
155  * This routine is called by the cm_Daemon() ie. the periodic daemon.
156  * every cm_daemonTokenCheckInterval seconds
157  */
158 void cm_CheckTokenCache(time_t now)
159 {
160     extern smb_vc_t *smb_allVCsp; /* global vcp list */
161     smb_vc_t   *vcp;
162     smb_user_t *usersp;
163     cm_user_t  *userp = NULL;
164     cm_ucell_t *ucellp;
165     BOOL bExpired=FALSE;
166
167     /*
168      * For every vcp, get the user and check his tokens
169      */
170     lock_ObtainRead(&smb_rctLock);
171     for (vcp=smb_allVCsp; vcp; vcp=vcp->nextp) {
172         for (usersp=vcp->usersp; usersp; usersp=usersp->nextp) {
173             if (usersp->unp) {
174                 if ((userp=usersp->unp->userp)==0)
175                     continue;
176             } else
177                 continue;
178             lock_ObtainMutex(&userp->mx);
179             for (ucellp=userp->cellInfop; ucellp; ucellp=ucellp->nextp) {
180                 if (ucellp->flags & CM_UCELLFLAG_RXKAD) {
181                     if (ucellp->expirationTime < now) {
182                         /* this guy's tokens have expired */
183                         osi_Log3(afsd_logp, "cm_CheckTokens: Tokens for user:%s have expired expiration time:0x%x ucellp:%x",
184                                  ucellp->userName, ucellp->expirationTime, ucellp);
185                         if (ucellp->ticketp) {
186                             free(ucellp->ticketp);
187                             ucellp->ticketp = NULL;
188                         }
189                         _InterlockedAnd(&ucellp->flags, ~CM_UCELLFLAG_RXKAD);
190                         ucellp->gen++;
191                         bExpired=TRUE;
192                     }
193                 }
194             }
195             lock_ReleaseMutex(&userp->mx);
196             if (bExpired) {
197                 bExpired=FALSE;
198                 cm_ResetACLCache(NULL, userp);
199             }
200         }
201     }
202     lock_ReleaseRead(&smb_rctLock);
203 }
204
205 #ifdef USE_ROOT_TOKENS
206 /*
207  * Service/Parameters/RootTokens/<cellname>/
208  * -> UseLSA
209  * -> Keytab (required if UseLSA is 0)
210  * -> Principal (required if there is more than one principal in the keytab)
211  * -> Realm (required if realm is not upper-case of <cellname>
212  * -> RequireEncryption
213  */
214
215 void
216 cm_RefreshRootTokens(void)
217 {
218
219 }
220 #endif