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