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