Windows: AFSTearDownExtents may experience active extents
[openafs.git] / src / WINNT / afsclass / c_usr.cpp
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 <winsock2.h>
11 #include <ws2tcpip.h>
12
13 extern "C" {
14 #include <afsconfig.h>
15 #include <afs/param.h>
16 #include <afs/stds.h>
17 #include <roken.h>
18 }
19
20 #include <WINNT/afsclass.h>
21 #include "internal.h"
22
23
24 /*
25  * DEFINITIONS ________________________________________________________________
26  *
27  */
28
29 #define USERACCESS_TO_ACCOUNTACCESS(_ua) ( ((_ua) == PTS_USER_OWNER_ACCESS) ? aaOWNER_ONLY : aaANYONE )
30
31
32 /*
33  * ROUTINES ___________________________________________________________________
34  *
35  */
36
37 USER::USER (LPCELL lpCellParent, LPTSTR pszPrincipal, LPTSTR pszInstance)
38 {
39    m_lpiCell = lpCellParent->GetIdentifier();
40    lstrcpy (m_szPrincipal, pszPrincipal);
41    lstrcpy (m_szInstance, (pszInstance) ? pszInstance : TEXT(""));
42
43    m_lpiThis = NULL;
44    m_fStatusOutOfDate = TRUE;
45    m_mszOwnerOf = NULL;
46    m_mszMemberOf = NULL;
47    memset(&m_us, 0, sizeof(m_us));
48 }
49
50
51 USER::~USER (void)
52 {
53    if (m_lpiThis)
54       m_lpiThis->m_cRef --;
55
56    FreeString (m_mszOwnerOf);
57    FreeString (m_mszMemberOf);
58 }
59
60
61 void USER::SendDeleteNotifications (void)
62 {
63    NOTIFYCALLBACK::SendNotificationToAll (evtDestroy, GetIdentifier());
64 }
65
66
67 void USER::Close (void)
68 {
69    AfsClass_Leave();
70 }
71
72
73 LPIDENT USER::GetIdentifier (void)
74 {
75    if (m_lpiThis == NULL)
76       {
77       if ((m_lpiThis = IDENT::FindIdent (this)) == NULL)
78          m_lpiThis = New2 (IDENT,(this));
79       m_lpiThis->m_cRef ++;
80       }
81
82    return m_lpiThis;
83 }
84
85
86 void USER::Invalidate (void)
87 {
88    m_fStatusOutOfDate = TRUE;
89 }
90
91
92 LPCELL USER::OpenCell (ULONG *pStatus)
93 {
94    return m_lpiCell->OpenCell (pStatus);
95 }
96
97
98 void USER::GetName (LPTSTR pszPrincipal, LPTSTR pszInstance)
99 {
100    if (pszPrincipal)
101       lstrcpy (pszPrincipal, m_szPrincipal);
102    if (pszInstance)
103       lstrcpy (pszInstance, m_szInstance);
104 }
105
106
107 BOOL USER::GetStatus (LPUSERSTATUS lpus, BOOL fNotify, ULONG *pStatus)
108 {
109    if (!RefreshStatus (fNotify, pStatus))
110       return FALSE;
111
112    memcpy (lpus, &m_us, sizeof(USERSTATUS));
113    return TRUE;
114 }
115
116
117 PVOID USER::GetUserParam (void)
118 {
119    return GetIdentifier()->GetUserParam();
120 }
121
122
123 void USER::SetUserParam (PVOID pUserParam)
124 {
125    GetIdentifier()->SetUserParam (pUserParam);
126 }
127
128
129 BOOL USER::GetOwnerOf (LPTSTR *ppmsz, ULONG *pStatus)
130 {
131    if (!RefreshStatus (TRUE, pStatus))
132       return FALSE;
133    *ppmsz = CloneMultiString (m_mszOwnerOf);
134    return TRUE;
135 }
136
137
138 BOOL USER::GetMemberOf (LPTSTR *ppmsz, ULONG *pStatus)
139 {
140    if (!RefreshStatus (TRUE, pStatus))
141       return FALSE;
142    *ppmsz = CloneMultiString (m_mszMemberOf);
143    return TRUE;
144 }
145
146
147 BOOL USER::RefreshStatus (BOOL fNotify, ULONG *pStatus)
148 {
149    BOOL rc = TRUE;
150    DWORD status = 0;
151    DWORD kasStatus = 0;
152    DWORD ptsStatus = 0;
153
154    if (m_fStatusOutOfDate)
155       {
156       m_fStatusOutOfDate = FALSE;
157
158       if (fNotify)
159          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusBegin, GetIdentifier());
160
161       memset (&m_us, 0x00, sizeof(m_us));
162
163       FreeString (m_mszOwnerOf);
164       m_mszOwnerOf = NULL;
165
166       FreeString (m_mszMemberOf);
167       m_mszMemberOf = NULL;
168
169       TCHAR szFullName[ cchNAME ];
170       AfsClass_GenFullUserName (szFullName, m_szPrincipal, m_szInstance);
171
172       LPCELL lpCell;
173       if ((lpCell = OpenCell (&status)) == NULL)
174          rc = FALSE;
175       else
176          {
177          PVOID hCell;
178          if ((hCell = lpCell->GetCellObject (&status)) == NULL)
179             rc = FALSE;
180          else
181             {
182             // Try to get KAS information.
183             //
184             WORKERPACKET wpGetKas;
185             wpGetKas.wpKasPrincipalGet.hCell = hCell;
186             wpGetKas.wpKasPrincipalGet.hServer = lpCell->GetKasObject (&kasStatus);
187             wpGetKas.wpKasPrincipalGet.pszPrincipal = m_szPrincipal;
188             wpGetKas.wpKasPrincipalGet.pszInstance = m_szInstance;
189
190             if (Worker_DoTask (wtaskKasPrincipalGet, &wpGetKas, &kasStatus))
191                {
192                m_us.fHaveKasInfo = TRUE;
193
194                TCHAR szLastModPrincipal[ cchNAME ];
195                TCHAR szLastModInstance[ cchNAME ];
196                CopyAnsiToString (szLastModPrincipal, wpGetKas.wpKasPrincipalGet.Data.lastModPrincipal.principal);
197                CopyAnsiToString (szLastModInstance, wpGetKas.wpKasPrincipalGet.Data.lastModPrincipal.instance);
198
199                m_us.KASINFO.fIsAdmin = (wpGetKas.wpKasPrincipalGet.Data.adminSetting == KAS_ADMIN) ? TRUE : FALSE;
200                m_us.KASINFO.fCanGetTickets = (wpGetKas.wpKasPrincipalGet.Data.tgsSetting == TGS) ? TRUE : FALSE;
201                m_us.KASINFO.fEncrypt = (wpGetKas.wpKasPrincipalGet.Data.encSetting == ENCRYPT) ? TRUE : FALSE;
202                m_us.KASINFO.fCanChangePassword = (wpGetKas.wpKasPrincipalGet.Data.cpwSetting == CHANGE_PASSWORD) ? TRUE : FALSE;
203                m_us.KASINFO.fCanReusePasswords = (wpGetKas.wpKasPrincipalGet.Data.rpwSetting == REUSE_PASSWORD) ? TRUE : FALSE;
204                AfsClass_UnixTimeToSystemTime (&m_us.KASINFO.timeExpires, wpGetKas.wpKasPrincipalGet.Data.userExpiration);
205                AfsClass_UnixTimeToSystemTime (&m_us.KASINFO.timeLastPwChange, wpGetKas.wpKasPrincipalGet.Data.lastChangePasswordTime);
206                AfsClass_UnixTimeToSystemTime (&m_us.KASINFO.timeLastMod, wpGetKas.wpKasPrincipalGet.Data.lastModTime);
207                m_us.KASINFO.lpiLastMod = IDENT::FindUser (m_lpiCell, szLastModPrincipal, szLastModInstance);
208                m_us.KASINFO.csecTicketLifetime = wpGetKas.wpKasPrincipalGet.Data.maxTicketLifetime;
209                m_us.KASINFO.keyVersion = wpGetKas.wpKasPrincipalGet.Data.keyVersion;
210                memcpy (&m_us.KASINFO.key.key, &wpGetKas.wpKasPrincipalGet.Data.key.key, ENCRYPTIONKEY_LEN);
211                m_us.KASINFO.dwKeyChecksum = wpGetKas.wpKasPrincipalGet.Data.keyCheckSum;
212                m_us.KASINFO.cdayPwExpire = wpGetKas.wpKasPrincipalGet.Data.daysToPasswordExpire;
213                m_us.KASINFO.cFailLogin = wpGetKas.wpKasPrincipalGet.Data.failLoginCount;
214                m_us.KASINFO.csecFailLoginLock = wpGetKas.wpKasPrincipalGet.Data.lockTime;
215                }
216
217             // Try to get PTS information.
218             //
219             WORKERPACKET wpGetPts;
220             wpGetPts.wpPtsUserGet.hCell = hCell;
221             wpGetPts.wpPtsUserGet.pszUser = szFullName;
222             if (Worker_DoTask (wtaskPtsUserGet, &wpGetPts, &ptsStatus))
223                {
224                m_us.fHavePtsInfo = TRUE;
225
226                m_us.PTSINFO.cgroupCreationQuota = wpGetPts.wpPtsUserGet.Entry.groupCreationQuota;
227                m_us.PTSINFO.cgroupMember = wpGetPts.wpPtsUserGet.Entry.groupMembershipCount;
228                m_us.PTSINFO.uidName = wpGetPts.wpPtsUserGet.Entry.nameUid;
229                m_us.PTSINFO.uidOwner = wpGetPts.wpPtsUserGet.Entry.ownerUid;
230                m_us.PTSINFO.uidCreator = wpGetPts.wpPtsUserGet.Entry.creatorUid;
231
232                CopyAnsiToString (m_us.PTSINFO.szOwner, wpGetPts.wpPtsUserGet.Entry.owner);
233                CopyAnsiToString (m_us.PTSINFO.szCreator, wpGetPts.wpPtsUserGet.Entry.creator);
234
235                m_us.PTSINFO.aaListStatus = USERACCESS_TO_ACCOUNTACCESS (wpGetPts.wpPtsUserGet.Entry.listStatus);
236                m_us.PTSINFO.aaGroupsOwned = USERACCESS_TO_ACCOUNTACCESS (wpGetPts.wpPtsUserGet.Entry.listGroupsOwned);
237                m_us.PTSINFO.aaMembership = USERACCESS_TO_ACCOUNTACCESS (wpGetPts.wpPtsUserGet.Entry.listMembership);
238                }
239
240             // Grab the list of groups to which this user belongs
241             //
242             WORKERPACKET wpBegin;
243             wpBegin.wpPtsUserMemberListBegin.hCell = hCell;
244             wpBegin.wpPtsUserMemberListBegin.pszUser = szFullName;
245             if (Worker_DoTask (wtaskPtsUserMemberListBegin, &wpBegin, &status))
246                {
247                for (;;)
248                   {
249                   TCHAR szGroup[ cchNAME ];
250
251                   WORKERPACKET wpNext;
252                   wpNext.wpPtsUserMemberListNext.hEnum = wpBegin.wpPtsUserMemberListBegin.hEnum;
253                   wpNext.wpPtsUserMemberListNext.pszGroup = szGroup;
254                   if (!Worker_DoTask (wtaskPtsUserMemberListNext, &wpNext))
255                      break;
256
257                   FormatMultiString (&m_mszMemberOf, FALSE, TEXT("%1"), TEXT("%s"), szGroup);
258                   }
259
260                WORKERPACKET wpDone;
261                wpDone.wpPtsUserMemberListDone.hEnum = wpBegin.wpPtsUserMemberListBegin.hEnum;
262                Worker_DoTask (wtaskPtsUserMemberListDone, &wpDone);
263                }
264
265             // Grab the list of groups which this user owns
266             //
267             wpBegin.wpPtsOwnedGroupListBegin.hCell = hCell;
268             wpBegin.wpPtsOwnedGroupListBegin.pszOwner = szFullName;
269             if (Worker_DoTask (wtaskPtsOwnedGroupListBegin, &wpBegin, &status))
270                {
271                for (;;)
272                   {
273                   TCHAR szGroup[ cchNAME ];
274
275                   WORKERPACKET wpNext;
276                   wpNext.wpPtsOwnedGroupListNext.hEnum = wpBegin.wpPtsOwnedGroupListBegin.hEnum;
277                   wpNext.wpPtsOwnedGroupListNext.pszGroup = szGroup;
278                   if (!Worker_DoTask (wtaskPtsOwnedGroupListNext, &wpNext))
279                      break;
280
281                   FormatMultiString (&m_mszOwnerOf, FALSE, TEXT("%1"), TEXT("%s"), szGroup);
282                   }
283
284                WORKERPACKET wpDone;
285                wpDone.wpPtsOwnedGroupListDone.hEnum = wpBegin.wpPtsOwnedGroupListBegin.hEnum;
286                Worker_DoTask (wtaskPtsOwnedGroupListDone, &wpDone);
287                }
288             }
289
290          lpCell->Close();
291          }
292
293       if (fNotify)
294          NOTIFYCALLBACK::SendNotificationToAll (evtRefreshStatusEnd, GetIdentifier(), ((rc) ? 0 : status));
295       }
296
297    if (rc && (!m_us.fHaveKasInfo) && (!status) && kasStatus)
298       {
299       status = kasStatus;
300       rc = FALSE;
301       }
302    if (rc && (!m_us.fHavePtsInfo) && (!status) && ptsStatus)
303       {
304       status = ptsStatus;
305       // not fatal; rc remains TRUE
306       }
307    if (pStatus && !rc)
308       *pStatus = status;
309    return TRUE;
310 }
311
312
313 void USER::SplitUserName (LPCTSTR pszFull, LPTSTR pszName, LPTSTR pszInstance)
314 {
315    if (pszName)
316       lstrcpy (pszName, pszFull);
317    if (pszInstance)
318       lstrcpy (pszInstance, TEXT(""));
319
320    if (!USER::IsMachineAccount (pszFull))
321       {
322       if (pszName && pszInstance)
323          {
324          LPTSTR pchDot;
325          if ((pchDot = (LPTSTR)lstrchr (pszName, TEXT('.'))) != NULL)
326             {
327             *pchDot = TEXT('\0');
328             lstrcpy (pszInstance, &pchDot[1]);
329             }
330          }
331       }
332 }
333
334
335 BOOL USER::IsMachineAccount (LPCTSTR pszName)
336 {
337    for ( ; pszName && *pszName; ++pszName)
338       {
339       if (!( (*pszName == TEXT('.')) || ((*pszName >= TEXT('0')) && (*pszName <= TEXT('9'))) ))
340          return FALSE;
341       }
342    return TRUE;
343 }
344