windows-admin-group-20040823
authorJeffrey Altman <jaltman@mit.edu>
Mon, 23 Aug 2004 16:49:45 +0000 (16:49 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 23 Aug 2004 16:49:45 +0000 (16:49 +0000)
Update text files for 1.3.71 and describe the new Windows Authorization
Group "AFS Client Admins"

====================
This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================

Add support for "AFS Client Admins" windows authortization group

====================

NTMakefile changes for Admin Group

16 files changed:
doc/txt/winnotes/afs-changes-since-1.2.txt
doc/txt/winnotes/afs-install-notes.txt
doc/txt/winnotes/afs-issues.txt
src/WINNT/afsd/fs.c
src/WINNT/afsd/smb3.c
src/WINNT/client_config/isadmin.cpp
src/WINNT/install/NSIS/AdminGroup.cpp [new file with mode: 0644]
src/WINNT/install/NSIS/NTMakefile
src/WINNT/install/NSIS/OpenAFS.nsi
src/WINNT/install/wix/custom/NTMakefile
src/WINNT/install/wix/custom/afscustom.cpp
src/WINNT/install/wix/custom/afscustom.h
src/WINNT/install/wix/lang/en_US/strings.wxl
src/WINNT/install/wix/lang/en_US/ui.wxi
src/WINNT/install/wix/openafs.wxs
src/config/NTMakefile.i386_nt40

index e11c196..82c39b9 100644 (file)
@@ -1,4 +1,14 @@
 Since 1.3.70:
+  * A new Windows authorization group "AFS Client Admins" is now 
+    created and populated with the members of the "Administrators"
+    group.  The group is used to determine which accounts on the
+    machine may be used to modify the AFS Client Configuration via
+    the UI and command line tools.  afs_config.exe, fs.exe, 
+
+  * Modify the WinLogon Logoff Event Handler to query NT4 domain
+    controllers for the remote profile path if Active Directory
+    services are not available.
+
   * Fix aklog.exe to not add the AFS ID to the username
 
   * PTS registration of new users to foreign cells has been added to 
index 69799bf..f2166d5 100644 (file)
@@ -1,4 +1,4 @@
-OpenAFS for Windows 1.3.70 Installation Notes
+OpenAFS for Windows 1.3.71 Installation Notes
 ---------------------------------------------
 
 The OpenAFS for Windows product was very poorly maintained throughout the 
@@ -97,7 +97,7 @@ discover cell information when it is not located in the local CellServDB file
 (\Program Files\OpenAFS\Client\CellServDB).
 
 
-5. OpenAFS for Windows 1.3.70 only supports Windows 2000, Windows XP, and 
+5. OpenAFS for Windows 1.3.71 only supports Windows 2000, Windows XP, and 
 Windows 2003.  Windows NT 4.0 and the entire Windows 9x/Me line are no
 longer supported.  Older releases of OpenAFS are available for download
 if those operating systems must be supported.  The last version with support
@@ -216,9 +216,9 @@ Usage: aklog [-d] [[-cell | -c] cell [-k krb_realm]]
    No commandline arguments means authenticate to the local cell.
 
 
-11. The AFS Server functionality provided with OpenAFS 1.3.70 might work but 
+11. The AFS Server functionality provided with OpenAFS 1.3.71 might work but 
 should be considered highly experimental.  It has not been thoroughly tested.
-Any data which would cause pain if lost should be stored in an OpenAFS 
+Any data which would cause pain if lost should not be stored in an OpenAFS 
 Server on Windows.
 
 A few notes on the usage of the AFS Client Service if it is going to be 
@@ -265,7 +265,7 @@ encrypted data transfer between the AFS client and the AFS servers.  This
 is often referred to as "fcrypt" mode.
 
 
-18. OpenAFS 1.3.70 adds support for authenticated SMB connections using 
+18. OpenAFS 1.3.71 adds support for authenticated SMB connections using 
 either NTLM or GSS SPNEGO (NTLM, Kerberos 5, ...).  In previous versions
 of OpenAFS the SMB connections were unauthenticated which left open the
 door for several security holes which could be used to obtain access to
@@ -326,11 +326,21 @@ When installing under Terminal Server, you must execute the NSIS installer
 will result in AFS not running properly.  The AFS Server should not 
 be installed on a machine with Terminal Server installed.
 
+
 24. AFS is a Unix native file system.  As such the OpenAFS client attempts
 to treat the files stored in AFS as they would be on Unix.  File and directory
 names beginning with a "." are automatically given the Hidden attribute so
 they will not normally be displayed.
 
+
+25. As of 1.3.71, the OpenAFS for Windows client supports a local Windows
+authorization group called "AFS Client Admins".  This group is used in
+place of the "Administrators" group to determine which users are allowed
+to modify the AFS Client Service configuration via either afs_config.exe
+or fs.exe.  During installation this group is created and the current
+contents of the Administrators group is copied.
+
+
 ------------------------------------------------------------------------
 
 Reporting Bugs:
index c640aba..741e748 100644 (file)
@@ -175,26 +175,24 @@ List of unfunded projects:
         12. miscellaneous
         13. need to add support for all of the new registry values since 1.2.8
   11. Identify why 16-bit DOS applications executed out of AFS fail
-  12. Create new Windows Security Group to which users can be added for them to become AFS 
-      Client Administrators
-  13. Add support for configurable Icon file representing AFS folders within the Explorer Shell
-  14. Documentation Documentation Documentation
-  15. Large File support (> 2GB)
-  16. Integrate KFW installation into the NSIS installer
-  17. Add support for record locking to AFS (requires changes to the servers)
-  18. Unicode enable the SMB/CIFS server.  OEM Code Pages: 
+  12. Add support for configurable Icon file representing AFS folders within the Explorer Shell
+  13. Documentation Documentation Documentation
+  14. Large File support (> 2GB)
+  15. Integrate KFW installation into the NSIS installer
+  16. Add support for record locking to AFS (requires changes to the servers)
+  17. Unicode enable the SMB/CIFS server.  OEM Code Pages: 
       1. prevent the use of interoperable file names
       2. force the use of paths no longer than 256 characters
       3. force share names to be no longer than 13 characters
       4. restrict authentication to ASCII only names and passwords
-  19. Complete implementation of CIFS Remote Administration Protocol
-  20. Correct the problems with overlapped writes which adversely affect 
+  18. Complete implementation of CIFS Remote Administration Protocol
+  19. Correct the problems with overlapped writes which adversely affect 
       Microsoft Office applications storing documents and temporary files
       within AFS volumes
-  21. Add support for SMB/CIFS Digital Signatures
-  22. Development of afsmap.exe tool to provide AFS aware NET USE functionality
+  20. Add support for SMB/CIFS Digital Signatures
+  21. Development of afsmap.exe tool to provide AFS aware NET USE functionality
       afsmap.exe <drive> <afs-path> [/PERSISTENT]
       afsmap.exe <drive> <unc-path> [/PERSISTENT]
       afsmap.exe <drive> /DELETE
-  23. Write-through caching appears to be unsupported.   Files copied to AFS
+  22. Write-through caching appears to be unsupported.   Files copied to AFS
       do not end up in the local cache.
index ac32533..5e960c5 100644 (file)
@@ -583,6 +583,8 @@ char *AclToString(acl)
     return mydata;
 }
 
+#define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
+
 BOOL IsAdmin (void)
 {
     static BOOL fAdmin = FALSE;
@@ -590,20 +592,54 @@ BOOL IsAdmin (void)
 
     if (!fTested)
     {
-        /* Obtain the SID for BUILTIN\Administrators. If this is Windows NT,
-         * expect this call to succeed; if it does not, we can presume that
-         * it's not NT and therefore the user always has administrative
-         * privileges.
+        /* Obtain the SID for the AFS client admin group.  If the group does
+         * not exist, then assume we have AFS client admin privileges.
          */
         PSID psidAdmin = NULL;
-        SID_IDENTIFIER_AUTHORITY auth = SECURITY_NT_AUTHORITY;
+        DWORD dwSize, dwSize2;
+        char pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
+        char *pszRefDomain = NULL;
+        SID_NAME_USE snu = SidTypeGroup;
+
+        dwSize = sizeof(pszAdminGroup);
+
+        if (!GetComputerName(pszAdminGroup, &dwSize)) {
+            /* Can't get computer name.  We return false in this case.
+               Retain fAdmin and fTested. This shouldn't happen.*/
+            return FALSE;
+        }
 
         fTested = TRUE;
 
-        if (!AllocateAndInitializeSid (&auth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin))
+        dwSize = 0;
+        dwSize2 = 0;
+
+        strcat(pszAdminGroup,"\\");
+        strcat(pszAdminGroup, AFSCLIENT_ADMIN_GROUPNAME);
+
+        LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
+        /* that should always fail. */
+
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+            /* if we can't find the group, then we allow the operation */
             fAdmin = TRUE;
-        else
-        {
+            return TRUE;
+        }
+
+        if (dwSize == 0 || dwSize2 == 0) {
+            /* Paranoia */
+            fAdmin = TRUE;
+            return TRUE;
+        }
+
+        psidAdmin = (PSID)malloc(dwSize); memset(psidAdmin,0,dwSize);
+        pszRefDomain = (char *)malloc(dwSize2);
+
+        if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
+            /* We can't lookup the group now even though we looked it up earlier.  
+               Could this happen? */
+            fAdmin = TRUE;
+        } else {
             /* Then open our current ProcessToken */
             HANDLE hToken;
 
@@ -624,13 +660,14 @@ BOOL IsAdmin (void)
                 if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
                 {
                     /* Look through the list of group SIDs and see if any of them
-                     * matches the Administrator group SID.
+                     * matches the AFS Client Admin group SID.
                      */
                     size_t iGroup = 0;
                     for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
                     {
-                        if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid))
+                        if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
                             fAdmin = TRUE;
+                        }
                     }
                 }
 
@@ -639,8 +676,8 @@ BOOL IsAdmin (void)
             }
         }
 
-        if (psidAdmin)
-            FreeSid (psidAdmin);
+        free(psidAdmin);
+        free(pszRefDomain);
     }
 
     return fAdmin;
@@ -1657,7 +1694,7 @@ register struct cmd_syndesc *as; {
     if ( checkserv.tinterval != 0 ) {
 #ifdef WIN32
         if ( !IsAdmin() ) {
-            fprintf (stderr,"Permission denied: requires Administrator access.\n");
+            fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
             return EACCES;
         }
 #else /* WIN32 */
@@ -1769,7 +1806,7 @@ register struct cmd_syndesc *as; {
     
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
 #else /* WIN32 */
@@ -1883,7 +1920,7 @@ register struct cmd_syndesc *as; {
 
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
 #else /* WIN32 */
@@ -2104,7 +2141,7 @@ register struct cmd_syndesc *as; {
     if (ti) {
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
 #else /* WIN32 */
@@ -2171,7 +2208,7 @@ register struct cmd_syndesc *as; {
     
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
 #else /* WIN32 */
@@ -2311,7 +2348,7 @@ register struct cmd_syndesc *as; {
 
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
 #else /* WIN32 */
@@ -2567,7 +2604,7 @@ register struct cmd_syndesc *as; {
 
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
 #else /* WIN32 */
@@ -2724,7 +2761,7 @@ static TraceCmd(struct cmd_syndesc *asp)
     
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
 #else /* WIN32 */
@@ -2780,7 +2817,7 @@ struct cmd_syndesc *as; {
     
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");  
         return EACCES;
     }
 #else /* WIN32 */
@@ -2845,7 +2882,7 @@ static afs_int32 SetCryptCmd(as)
  
 #ifdef WIN32
     if ( !IsAdmin() ) {
-        fprintf (stderr,"Permission denied: requires Administrator access.\n");
+        fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
         return EACCES;
     }
 #else /* WIN32 */
@@ -3239,20 +3276,20 @@ static MemDumpCmd(struct cmd_syndesc *asp)
 
 static CSCPolicyCmd(struct cmd_syndesc *asp)
 {
-       struct cmd_item *ti;
-       char *share = NULL;
+    struct cmd_item *ti;
+    char *share = NULL;
     HKEY hkCSCPolicy;
 
-       for(ti=asp->parms[0].items; ti;ti=ti->next) {
-               share = ti->data;
-               if (share)
-               {
-                       break;
-               }
-       }
+    for(ti=asp->parms[0].items; ti;ti=ti->next) {
+        share = ti->data;
+        if (share)
+        {
+            break;
+        }
+    }
 
-       if (share)
-       {
+    if (share)
+    {
         char *policy;
 
         RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
@@ -3265,40 +3302,44 @@ static CSCPolicyCmd(struct cmd_syndesc *asp)
                         &hkCSCPolicy,
                         NULL );
 
-        if ( !IsAdmin() || hkCSCPolicy == NULL ) {
+        if ( hkCSCPolicy == NULL ) {
             fprintf (stderr,"Permission denied: requires Administrator access.\n");
-            if ( hkCSCPolicy )
-                RegCloseKey(hkCSCPolicy);
+            return EACCES;
+        }
+
+        if ( !IsAdmin() ) {
+            fprintf (stderr,"Permission denied: requires AFS Client Administrator access.\n");
+            RegCloseKey(hkCSCPolicy);
             return EACCES;
         }
 
         policy = "manual";
                
-               if (asp->parms[1].items)
-                       policy = "manual";
-               if (asp->parms[2].items)
-                       policy = "programs";
-               if (asp->parms[3].items)
-                       policy = "documents";
-               if (asp->parms[4].items)
-                       policy = "disable";
+        if (asp->parms[1].items)
+            policy = "manual";
+        if (asp->parms[2].items)
+            policy = "programs";
+        if (asp->parms[3].items)
+            policy = "documents";
+        if (asp->parms[4].items)
+            policy = "disable";
                
         RegSetValueEx( hkCSCPolicy, share, 0, REG_SZ, policy, strlen(policy)+1);
                
-               printf("CSC policy on share \"%s\" changed to \"%s\".\n\n", share, policy);
-               printf("Close all applications that accessed files on this share or restart AFS Client for the change to take effect.\n"); 
-       }
-       else
-       {
+        printf("CSC policy on share \"%s\" changed to \"%s\".\n\n", share, policy);
+        printf("Close all applications that accessed files on this share or restart AFS Client for the change to take effect.\n"); 
+    }
+    else
+    {
         DWORD dwIndex, dwPolicies;
-               char policyName[256];
-               DWORD policyNameLen;
+        char policyName[256];
+        DWORD policyNameLen;
         char policy[256];
         DWORD policyLen;
         DWORD dwType;
 
-               /* list current csc policies */
-               
+        /* list current csc policies */
+
         RegCreateKeyEx( HKEY_LOCAL_MACHINE, 
                         "SOFTWARE\\OpenAFS\\Client\\CSCPolicy",
                         0, 
@@ -3323,7 +3364,7 @@ static CSCPolicyCmd(struct cmd_syndesc *asp)
                          NULL   /* lpftLastWriteTime */
                          );
                
-               printf("Current CSC policies:\n");
+        printf("Current CSC policies:\n");
         for ( dwIndex = 0; dwIndex < dwPolicies; dwIndex ++ ) {
 
             policyNameLen = sizeof(policyName);
@@ -3331,10 +3372,10 @@ static CSCPolicyCmd(struct cmd_syndesc *asp)
             RegEnumValue( hkCSCPolicy, dwIndex, policyName, &policyNameLen, NULL,
                           &dwType, policy, &policyLen);
 
-                       printf("  %s = %s\n", policyName, policy);
-               }
-       }
+            printf("  %s = %s\n", policyName, policy);
+        }
+    }
 
     RegCloseKey(hkCSCPolicy);
-       return (0);
+    return (0);
 }
index d9a3f18..5b43ef9 100644 (file)
@@ -5861,211 +5861,211 @@ void smb_NotifyChange(DWORD action, DWORD notifyFilter,
        cm_scache_t *dscp, char *filename, char *otherFilename,
        BOOL isDirectParent)
 {
-       smb_packet_t *watch, *lastWatch, *nextWatch;
-       ULONG parmSlot, parmCount, parmOffset, dataOffset, nameLen;
-       char *outData, *oldOutData;
-       ULONG filter;
-       USHORT fid, wtree;
-       ULONG maxLen;
-       BOOL twoEntries = FALSE;
-       ULONG otherNameLen, oldParmCount = 0;
-       DWORD otherAction;
-       smb_vc_t *vcp;
-       smb_fid_t *fidp;
+    smb_packet_t *watch, *lastWatch, *nextWatch;
+    ULONG parmSlot, parmCount, parmOffset, dataOffset, nameLen;
+    char *outData, *oldOutData;
+    ULONG filter;
+    USHORT fid, wtree;
+    ULONG maxLen;
+    BOOL twoEntries = FALSE;
+    ULONG otherNameLen, oldParmCount = 0;
+    DWORD otherAction;
+    smb_vc_t *vcp;
+    smb_fid_t *fidp;
 
-       /* Get ready for rename within directory */
-       if (action == FILE_ACTION_RENAMED_OLD_NAME && otherFilename != NULL) {
-               twoEntries = TRUE;
-               otherAction = FILE_ACTION_RENAMED_NEW_NAME;
-       }
+    /* Get ready for rename within directory */
+    if (action == FILE_ACTION_RENAMED_OLD_NAME && otherFilename != NULL) {
+        twoEntries = TRUE;
+        otherAction = FILE_ACTION_RENAMED_NEW_NAME;
+    }
 
     osi_Log2(smb_logp,"in smb_NotifyChange for file [%s] dscp [%x]",
-              osi_LogSaveString(smb_logp,filename),dscp);
-
-       lock_ObtainMutex(&smb_Dir_Watch_Lock);
-       watch = smb_Directory_Watches;
-       while (watch) {
-               filter = smb_GetSMBParm(watch, 19)
-                               | (smb_GetSMBParm(watch, 20) << 16);
-               fid = smb_GetSMBParm(watch, 21);
-               wtree = smb_GetSMBParm(watch, 22) & 0xffff;  /* TODO: should this be 0xff ? */
-               maxLen = smb_GetSMBOffsetParm(watch, 5, 1)
-                               | (smb_GetSMBOffsetParm(watch, 6, 1) << 16);
-               vcp = watch->vcp;
-
-               /*
-                * Strange hack - bug in NT Client and NT Server that we
-                * must emulate?
-                */
-               if (filter == 3 && wtree)
-                       filter = 0x17;
+             osi_LogSaveString(smb_logp,filename),dscp);
+
+    lock_ObtainMutex(&smb_Dir_Watch_Lock);
+    watch = smb_Directory_Watches;
+    while (watch) {
+        filter = smb_GetSMBParm(watch, 19)
+            | (smb_GetSMBParm(watch, 20) << 16);
+        fid = smb_GetSMBParm(watch, 21);
+        wtree = smb_GetSMBParm(watch, 22) & 0xffff;  /* TODO: should this be 0xff ? */
+        maxLen = smb_GetSMBOffsetParm(watch, 5, 1)
+            | (smb_GetSMBOffsetParm(watch, 6, 1) << 16);
+        vcp = watch->vcp;
+
+        /*
+         * Strange hack - bug in NT Client and NT Server that we
+         * must emulate?
+         */
+        if (filter == 3 && wtree)
+            filter = 0x17;
 
-               fidp = smb_FindFID(vcp, fid, 0);
+        fidp = smb_FindFID(vcp, fid, 0);
         if (!fidp) {
             osi_Log1(smb_logp," no fidp for fid[%d]",fid);
-               lastWatch = watch;
-               watch = watch->nextp;
-               continue;
-        }
-               if (fidp->scp != dscp
-                   || (filter & notifyFilter) == 0
-                   || (!isDirectParent && !wtree)) {
+            lastWatch = watch;
+            watch = watch->nextp;
+            continue;
+        }       
+        if (fidp->scp != dscp
+             || (filter & notifyFilter) == 0
+             || (!isDirectParent && !wtree)) {
             osi_Log1(smb_logp," passing fidp->scp[%x]", fidp->scp);
             smb_ReleaseFID(fidp);
-                       lastWatch = watch;
-                       watch = watch->nextp;
-                       continue;
-               }
-               smb_ReleaseFID(fidp);
+            lastWatch = watch;
+            watch = watch->nextp;
+            continue;
+        }
+        smb_ReleaseFID(fidp);
 
-               osi_Log4(smb_logp,
-                        "Sending Change Notification for fid %d filter 0x%x wtree %d file %s",
-                        fid, filter, wtree, osi_LogSaveString(smb_logp, filename));
+        osi_Log4(smb_logp,
+                  "Sending Change Notification for fid %d filter 0x%x wtree %d file %s",
+                  fid, filter, wtree, osi_LogSaveString(smb_logp, filename));
 
-               nextWatch = watch->nextp;
-               if (watch == smb_Directory_Watches)
-                       smb_Directory_Watches = nextWatch;
-               else
-                       lastWatch->nextp = nextWatch;
+        nextWatch = watch->nextp;
+        if (watch == smb_Directory_Watches)
+            smb_Directory_Watches = nextWatch;
+        else
+            lastWatch->nextp = nextWatch;
 
-               /* Turn off WATCHED flag in dscp */
-               lock_ObtainMutex(&dscp->mx);
-               if (wtree)
-                       dscp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
-               else
-                       dscp->flags &= ~CM_SCACHEFLAG_WATCHED;
-               lock_ReleaseMutex(&dscp->mx);
+        /* Turn off WATCHED flag in dscp */
+        lock_ObtainMutex(&dscp->mx);
+        if (wtree)
+            dscp->flags &= ~CM_SCACHEFLAG_WATCHEDSUBTREE;
+        else
+            dscp->flags &= ~CM_SCACHEFLAG_WATCHED;
+        lock_ReleaseMutex(&dscp->mx);
 
-               /* Convert to response packet */
-               ((smb_t *) watch)->reb = 0x80;
-               ((smb_t *) watch)->wct = 0;
+        /* Convert to response packet */
+        ((smb_t *) watch)->reb = 0x80;
+        ((smb_t *) watch)->wct = 0;
 
-               /* out parms */
-               if (filename == NULL)
-                       parmCount = 0;
-               else {
-                       nameLen = strlen(filename);
-                       parmCount = 3*4 + nameLen*2;
-                       parmCount = (parmCount + 3) & ~3;       /* pad to 4 */
-                       if (twoEntries) {
-                               otherNameLen = strlen(otherFilename);
-                               oldParmCount = parmCount;
-                               parmCount += 3*4 + otherNameLen*2;
-                               parmCount = (parmCount + 3) & ~3; /* pad to 4 */
-                       }
-                       if (maxLen < parmCount)
-                               parmCount = 0;  /* not enough room */
-               }
-               parmOffset = 8*4 + 39;
-               parmOffset += 1;                        /* pad to 4 */
-               dataOffset = parmOffset + parmCount;
-
-               parmSlot = 1;
-               watch->oddByte = 1;
-               /* Total Parameter Count */
-               smb_SetSMBParmLong(watch, parmSlot, parmCount); parmSlot += 2;
-               /* Total Data Count */
-               smb_SetSMBParmLong(watch, parmSlot, 0); parmSlot += 2;
-               /* Parameter Count */
-               smb_SetSMBParmLong(watch, parmSlot, parmCount); parmSlot += 2;
-               /* Parameter Offset */
-               smb_SetSMBParmLong(watch, parmSlot, parmOffset); parmSlot += 2;
-               /* Parameter Displacement */
-               smb_SetSMBParmLong(watch, parmSlot, 0); parmSlot += 2;
-               /* Data Count */
-               smb_SetSMBParmLong(watch, parmSlot, 0); parmSlot += 2;
-               /* Data Offset */
-               smb_SetSMBParmLong(watch, parmSlot, dataOffset); parmSlot += 2;
-               /* Data Displacement */
-               smb_SetSMBParmLong(watch, parmSlot, 0); parmSlot += 2;
-               smb_SetSMBParmByte(watch, parmSlot, 0); /* Setup Count */
-               smb_SetSMBDataLength(watch, parmCount + 1);
-
-               if (parmCount != 0) {
-                       outData = smb_GetSMBData(watch, NULL);
-                       outData++;      /* round to get to parmOffset */
-                       oldOutData = outData;
-                       *((DWORD *)outData) = oldParmCount; outData += 4;
-                                       /* Next Entry Offset */
-                       *((DWORD *)outData) = action; outData += 4;
-                                       /* Action */
-                       *((DWORD *)outData) = nameLen*2; outData += 4;
-                                       /* File Name Length */
-                       mbstowcs((WCHAR *)outData, filename, nameLen);
-                                       /* File Name */
-                       if (twoEntries) {
-                               outData = oldOutData + oldParmCount;
-                               *((DWORD *)outData) = 0; outData += 4;
-                                       /* Next Entry Offset */
-                               *((DWORD *)outData) = otherAction; outData += 4;
-                                       /* Action */
-                               *((DWORD *)outData) = otherNameLen*2;
-                               outData += 4;   /* File Name Length */
-                               mbstowcs((WCHAR *)outData, otherFilename,
-                                        otherNameLen); /* File Name */
-                       }
-               }
+        /* out parms */
+        if (filename == NULL)
+            parmCount = 0;
+        else {
+            nameLen = strlen(filename);
+            parmCount = 3*4 + nameLen*2;
+            parmCount = (parmCount + 3) & ~3;  /* pad to 4 */
+            if (twoEntries) {
+                otherNameLen = strlen(otherFilename);
+                oldParmCount = parmCount;
+                parmCount += 3*4 + otherNameLen*2;
+                parmCount = (parmCount + 3) & ~3; /* pad to 4 */
+            }
+            if (maxLen < parmCount)
+                parmCount = 0; /* not enough room */
+        }
+        parmOffset = 8*4 + 39;
+        parmOffset += 1;                       /* pad to 4 */
+        dataOffset = parmOffset + parmCount;
 
-               /*
-                * If filename is null, we don't know the cause of the
-                * change notification.  We return zero data (see above),
-                * and set error code to NT_STATUS_NOTIFY_ENUM_DIR
-                * (= 0x010C).  We set the error code here by hand, without
-                * modifying wct and bcc.
-                */
-               if (filename == NULL) {
-                       ((smb_t *) watch)->rcls = 0x0C;
-                       ((smb_t *) watch)->reh = 0x01;
-                       ((smb_t *) watch)->errLow = 0;
-                       ((smb_t *) watch)->errHigh = 0;
-                       /* Set NT Status codes flag */
-                       ((smb_t *) watch)->flg2 |= 0x4000;
-               }
+        parmSlot = 1;
+        watch->oddByte = 1;
+        /* Total Parameter Count */
+        smb_SetSMBParmLong(watch, parmSlot, parmCount); parmSlot += 2;
+        /* Total Data Count */
+        smb_SetSMBParmLong(watch, parmSlot, 0); parmSlot += 2;
+        /* Parameter Count */
+        smb_SetSMBParmLong(watch, parmSlot, parmCount); parmSlot += 2;
+        /* Parameter Offset */
+        smb_SetSMBParmLong(watch, parmSlot, parmOffset); parmSlot += 2;
+        /* Parameter Displacement */
+        smb_SetSMBParmLong(watch, parmSlot, 0); parmSlot += 2;
+        /* Data Count */
+        smb_SetSMBParmLong(watch, parmSlot, 0); parmSlot += 2;
+        /* Data Offset */
+        smb_SetSMBParmLong(watch, parmSlot, dataOffset); parmSlot += 2;
+        /* Data Displacement */
+        smb_SetSMBParmLong(watch, parmSlot, 0); parmSlot += 2;
+        smb_SetSMBParmByte(watch, parmSlot, 0);        /* Setup Count */
+        smb_SetSMBDataLength(watch, parmCount + 1);
+
+        if (parmCount != 0) {
+            outData = smb_GetSMBData(watch, NULL);
+            outData++; /* round to get to parmOffset */
+            oldOutData = outData;
+            *((DWORD *)outData) = oldParmCount; outData += 4;
+            /* Next Entry Offset */
+            *((DWORD *)outData) = action; outData += 4;
+            /* Action */
+            *((DWORD *)outData) = nameLen*2; outData += 4;
+            /* File Name Length */
+            mbstowcs((WCHAR *)outData, filename, nameLen);
+            /* File Name */
+            if (twoEntries) {
+                outData = oldOutData + oldParmCount;
+                *((DWORD *)outData) = 0; outData += 4;
+                /* Next Entry Offset */
+                *((DWORD *)outData) = otherAction; outData += 4;
+                /* Action */
+                *((DWORD *)outData) = otherNameLen*2;
+                outData += 4;  /* File Name Length */
+                mbstowcs((WCHAR *)outData, otherFilename,
+                          otherNameLen);       /* File Name */
+            }       
+        }       
+
+        /*
+         * If filename is null, we don't know the cause of the
+         * change notification.  We return zero data (see above),
+         * and set error code to NT_STATUS_NOTIFY_ENUM_DIR
+         * (= 0x010C).  We set the error code here by hand, without
+         * modifying wct and bcc.
+         */
+        if (filename == NULL) {
+            ((smb_t *) watch)->rcls = 0x0C;
+            ((smb_t *) watch)->reh = 0x01;
+            ((smb_t *) watch)->errLow = 0;
+            ((smb_t *) watch)->errHigh = 0;
+            /* Set NT Status codes flag */
+            ((smb_t *) watch)->flg2 |= 0x4000;
+        }
 
-               smb_SendPacket(vcp, watch);
+        smb_SendPacket(vcp, watch);
         smb_ReleaseVC(vcp);
-               smb_FreePacket(watch);
-               watch = nextWatch;
-       }
-       lock_ReleaseMutex(&smb_Dir_Watch_Lock);
-}
+        smb_FreePacket(watch);
+        watch = nextWatch;
+    }
+    lock_ReleaseMutex(&smb_Dir_Watch_Lock);
+}       
 
 long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
 {
-       unsigned char *replyWctp;
-       smb_packet_t *watch, *lastWatch;
-       USHORT fid, watchtree;
-       smb_fid_t *fidp;
-       cm_scache_t *scp;
-
-       osi_Log0(smb_logp, "SMB3 receive NT cancel");
+    unsigned char *replyWctp;
+    smb_packet_t *watch, *lastWatch;
+    USHORT fid, watchtree;
+    smb_fid_t *fidp;
+    cm_scache_t *scp;
 
-       lock_ObtainMutex(&smb_Dir_Watch_Lock);
-       watch = smb_Directory_Watches;
-       while (watch) {
-               if (((smb_t *)watch)->uid == ((smb_t *)inp)->uid
-                   && ((smb_t *)watch)->pid == ((smb_t *)inp)->pid
-                   && ((smb_t *)watch)->mid == ((smb_t *)inp)->mid
-                   && ((smb_t *)watch)->tid == ((smb_t *)inp)->tid) {
-                       if (watch == smb_Directory_Watches)
-                               smb_Directory_Watches = watch->nextp;
-                       else
-                               lastWatch->nextp = watch->nextp;
-                       lock_ReleaseMutex(&smb_Dir_Watch_Lock);
+    osi_Log0(smb_logp, "SMB3 receive NT cancel");
+
+    lock_ObtainMutex(&smb_Dir_Watch_Lock);
+    watch = smb_Directory_Watches;
+    while (watch) {
+        if (((smb_t *)watch)->uid == ((smb_t *)inp)->uid
+             && ((smb_t *)watch)->pid == ((smb_t *)inp)->pid
+             && ((smb_t *)watch)->mid == ((smb_t *)inp)->mid
+             && ((smb_t *)watch)->tid == ((smb_t *)inp)->tid) {
+            if (watch == smb_Directory_Watches)
+                smb_Directory_Watches = watch->nextp;
+            else
+                lastWatch->nextp = watch->nextp;
+            lock_ReleaseMutex(&smb_Dir_Watch_Lock);
 
-                       /* Turn off WATCHED flag in scp */
-                       fid = smb_GetSMBParm(watch, 21);
-                       watchtree = smb_GetSMBParm(watch, 22) & 0xffff;
+            /* Turn off WATCHED flag in scp */
+            fid = smb_GetSMBParm(watch, 21);
+            watchtree = smb_GetSMBParm(watch, 22) & 0xffff;
 
             if (vcp != watch->vcp)
                 osi_Log2(smb_logp, "smb_ReceiveNTCancel: vcp %x not equal to watch vcp %x", 
-                         vcp, watch->vcp);
+                          vcp, watch->vcp);
 
-                       fidp = smb_FindFID(vcp, fid, 0);
+            fidp = smb_FindFID(vcp, fid, 0);
             if (fidp) {
                 osi_Log3(smb_logp, "Cancelling change notification for fid %d wtree %d file %s", 
-                         fid, watchtree,
-                         osi_LogSaveString(smb_logp, (fidp)?fidp->NTopen_wholepathp:""));
+                          fid, watchtree,
+                          osi_LogSaveString(smb_logp, (fidp)?fidp->NTopen_wholepathp:""));
 
                 scp = fidp->scp;
                 lock_ObtainMutex(&scp->mx);
@@ -6079,28 +6079,28 @@ long smb_ReceiveNTCancel(smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp)
                 osi_Log2(smb_logp,"NTCancel unable to resolve fid [%d] in vcp[%x]", fid,vcp);
             }
 
-                       /* assume STATUS32; return 0xC0000120 (CANCELED) */
-                       replyWctp = watch->wctp;
-                       *replyWctp++ = 0;
-                       *replyWctp++ = 0;
-                       *replyWctp++ = 0;
-                       ((smb_t *)watch)->rcls = 0x20;
-                       ((smb_t *)watch)->reh = 0x1;
-                       ((smb_t *)watch)->errLow = 0;
-                       ((smb_t *)watch)->errHigh = 0xC0;
-                       ((smb_t *)watch)->flg2 |= 0x4000;
-                       smb_SendPacket(vcp, watch);
+            /* assume STATUS32; return 0xC0000120 (CANCELED) */
+            replyWctp = watch->wctp;
+            *replyWctp++ = 0;
+            *replyWctp++ = 0;
+            *replyWctp++ = 0;
+            ((smb_t *)watch)->rcls = 0x20;
+            ((smb_t *)watch)->reh = 0x1;
+            ((smb_t *)watch)->errLow = 0;
+            ((smb_t *)watch)->errHigh = 0xC0;
+            ((smb_t *)watch)->flg2 |= 0x4000;
+            smb_SendPacket(vcp, watch);
             if (watch->vcp)
                 smb_ReleaseVC(watch->vcp);
-                       smb_FreePacket(watch);
-                       return 0;
-               }
-               lastWatch = watch;
-               watch = watch->nextp;
-       }
-       lock_ReleaseMutex(&smb_Dir_Watch_Lock);
+            smb_FreePacket(watch);
+            return 0;
+        }
+        lastWatch = watch;
+        watch = watch->nextp;
+    }
+    lock_ReleaseMutex(&smb_Dir_Watch_Lock);
 
-       return 0;
+    return 0;
 }
 
 void smb3_Init()
index c2c1aca..2013b7b 100644 (file)
@@ -50,63 +50,103 @@ BOOL IsWindowsNT (void)
  *
  */
 
+#define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins"
+
 BOOL IsAdmin (void)
 {
-   static BOOL fAdmin = FALSE;
-   static BOOL fTested = FALSE;
-   if (!fTested)
-      {
-      fTested = TRUE;
-
-      // Obtain the SID for BUILTIN\Administrators. If this is Windows NT,
-      // expect this call to succeed; if it does not, we can presume that
-      // it's not NT and therefore the user always has administrative
-      // privileges.
-      //
-      PSID psidAdmin = NULL;
-      SID_IDENTIFIER_AUTHORITY auth = SECURITY_NT_AUTHORITY;
-      if (!AllocateAndInitializeSid (&auth, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &psidAdmin))
-         fAdmin = TRUE;
-      else
-         {
-
-         // Then open our current ProcessToken
-         //
-         HANDLE hToken;
-         if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
+    static BOOL fAdmin = FALSE;
+    static BOOL fTested = FALSE;
+
+    if (!fTested)
+    {
+        /* Obtain the SID for the AFS client admin group.  If the group does
+         * not exist, then assume we have AFS client admin privileges.
+         */
+        PSID psidAdmin = NULL;
+        DWORD dwSize, dwSize2;
+        char pszAdminGroup[ MAX_COMPUTERNAME_LENGTH + sizeof(AFSCLIENT_ADMIN_GROUPNAME) + 2 ];
+        char *pszRefDomain = NULL;
+        SID_NAME_USE snu = SidTypeGroup;
+
+        dwSize = sizeof(pszAdminGroup);
+
+        if (!GetComputerName(pszAdminGroup, &dwSize)) {
+            /* Can't get computer name.  We return false in this case.
+               Retain fAdmin and fTested. This shouldn't happen.*/
+            return FALSE;
+        }
+
+        fTested = TRUE;
+
+        dwSize = 0;
+        dwSize2 = 0;
+
+        strcat(pszAdminGroup,"\\");
+        strcat(pszAdminGroup, AFSCLIENT_ADMIN_GROUPNAME);
+
+        LookupAccountName(NULL, pszAdminGroup, NULL, &dwSize, NULL, &dwSize2, &snu);
+        /* that should always fail. */
+
+        if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+            /* if we can't find the group, then we allow the operation */
+            fAdmin = TRUE;
+            return TRUE;
+        }
+
+        if (dwSize == 0 || dwSize2 == 0) {
+            /* Paranoia */
+            fAdmin = TRUE;
+            return TRUE;
+        }
+
+        psidAdmin = (PSID) malloc(dwSize); memset(psidAdmin,0,dwSize);
+        pszRefDomain = (char *)malloc(dwSize2);
+
+        if (!LookupAccountName(NULL, pszAdminGroup, psidAdmin, &dwSize, pszRefDomain, &dwSize2, &snu)) {
+            /* We can't lookup the group now even though we looked it up earlier.  
+               Could this happen? */
+            fAdmin = TRUE;
+        } else {
+            /* Then open our current ProcessToken */
+            HANDLE hToken;
+
+            if (OpenProcessToken (GetCurrentProcess(), TOKEN_QUERY, &hToken))
             {
-
-            // We'll have to allocate a chunk of memory to store the list of
-            // groups to which this user belongs; find out how much memory
-            // we'll need.
-            //
-            DWORD dwSize = 0;
-            GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
+                /* We'll have to allocate a chunk of memory to store the list of
+                 * groups to which this user belongs; find out how much memory
+                 * we'll need.
+                 */
+                DWORD dwSize = 0;
+                PTOKEN_GROUPS pGroups;
+                
+                GetTokenInformation (hToken, TokenGroups, NULL, dwSize, &dwSize);
             
-            // Allocate that buffer, and read in the list of groups.
-            //
-            PTOKEN_GROUPS pGroups = (PTOKEN_GROUPS)Allocate (dwSize);
-            if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
-               {
-               // Look through the list of group SIDs and see if any of them
-               // matches the Administrator group SID.
-               //
-               for (size_t iGroup = 0; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
-                  {
-                  if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid))
-                     fAdmin = TRUE;
-                  }
-               }
-
-            if (pGroups)
-               Free (pGroups);
+                pGroups = (PTOKEN_GROUPS)malloc(dwSize);
+                
+                /* Allocate that buffer, and read in the list of groups. */
+                if (GetTokenInformation (hToken, TokenGroups, pGroups, dwSize, &dwSize))
+                {
+                    /* Look through the list of group SIDs and see if any of them
+                     * matches the AFS Client Admin group SID.
+                     */
+                    size_t iGroup = 0;
+                    for (; (!fAdmin) && (iGroup < pGroups->GroupCount); ++iGroup)
+                    {
+                        if (EqualSid (psidAdmin, pGroups->Groups[ iGroup ].Sid)) {
+                            fAdmin = TRUE;
+                        }
+                    }
+                }
+
+                if (pGroups)
+                    free(pGroups);
             }
-         }
+        }
 
-      if (psidAdmin)
-         FreeSid (psidAdmin);
-      }
+        free(psidAdmin);
+        free(pszRefDomain);
+    }
 
-   return fAdmin;
+    return fAdmin;
 }
 
diff --git a/src/WINNT/install/NSIS/AdminGroup.cpp b/src/WINNT/install/NSIS/AdminGroup.cpp
new file mode 100644 (file)
index 0000000..e3adcac
--- /dev/null
@@ -0,0 +1,89 @@
+#include<windows.h>
+#include<string.h>
+#include<stdio.h>
+#include<lm.h>
+
+#pragma comment(lib,"netapi32.lib")
+
+#define AFSCLIENT_ADMIN_GROUPNAMEW L"AFS Client Admins"
+#define AFSCLIENT_ADMIN_COMMENTW L"AFS Client Administrators"
+
+UINT createAfsAdminGroup(void) {
+    LOCALGROUP_INFO_1 gInfo;
+    DWORD dwError;
+    NET_API_STATUS status;
+
+    gInfo.lgrpi1_name = AFSCLIENT_ADMIN_GROUPNAMEW;
+    gInfo.lgrpi1_comment = AFSCLIENT_ADMIN_COMMENTW;
+    status = NetLocalGroupAdd(NULL, 1, (LPBYTE) &gInfo, &dwError);
+
+    return status;
+}
+
+UINT initializeAfsAdminGroup(void) {
+    PSID psidAdmin = NULL;
+    SID_IDENTIFIER_AUTHORITY auth = SECURITY_NT_AUTHORITY;
+    NET_API_STATUS status;
+    LOCALGROUP_MEMBERS_INFO_0 *gmAdmins = NULL;
+    DWORD dwNEntries, dwTEntries;
+
+    status = NetLocalGroupGetMembers(NULL, L"Administrators", 0, (LPBYTE *) &gmAdmins, MAX_PREFERRED_LENGTH, &dwNEntries, &dwTEntries, NULL);
+    if(status)
+        return status;
+
+    status = NetLocalGroupAddMembers(NULL, AFSCLIENT_ADMIN_GROUPNAMEW, 0, (LPBYTE) gmAdmins, dwNEntries);
+
+    NetApiBufferFree( gmAdmins );
+
+    return status;
+}
+
+UINT removeAfsAdminGroup(void) {
+    NET_API_STATUS status;
+    status = NetLocalGroupDel(NULL, AFSCLIENT_ADMIN_GROUPNAMEW);
+    return status;
+}
+
+void showUsage(char * progname) {
+    printf(
+        "Usage: %s [-create | -remove]\n"
+        "  -create : Create AFS Client Admins group and populate it with\n"
+        "            the members of the Administrators group\n"
+        "  -remove : Remove the AFS Client Admins group\n"
+        , progname);
+}
+
+int main(int argc, char ** argv) {
+
+    UINT rv = 0;
+
+    if(argc < 2) {
+        showUsage(argv[0]);
+        return 1;
+    }
+
+    if(stricmp(argv[1], "-create")) {
+        rv = createAfsAdminGroup();
+        if(rv) {
+            if(rv != ERROR_ALIAS_EXISTS) {
+            fprintf(stderr, "%s: Can't create AFS Client Admin group. NetApi error %u\n", rv);
+            } else {
+                /* The group already exists. (Preserved config from a
+                   prior install). */
+                rv = 0;
+            }
+        } else {
+            rv = initializeAfsAdminGroup();
+            if(rv)
+                fprintf(stderr, "%s: Can't populate AFS Client Admin group. NetApi error %u\n", rv);
+        }
+    } else if(stricmp(argv[1], "-remove")) {
+        removeAfsAdminGroup();
+        rv = 0;
+    } else {
+        showUsage(argv[0]);
+        rv = 0;
+    }
+
+    return rv;
+}
\ No newline at end of file
index b90525f..69a6791 100644 (file)
@@ -22,6 +22,12 @@ $(OUT)\Killer.obj: Killer.cpp
 $(EXEDIR)\Killer.exe: $(OUT)\Killer.obj
       $(EXECONLINK) $(OUT)\Killer.obj
 
+$(OUT)\AdminGroup.obj: AdminGroup.cpp
+      $(C2OBJ) AdminGroup.cpp
+
+$(EXEDIR)\AdminGroup.exe: $(OUT)\AdminGroup.obj
+      $(EXECONLINK) $(OUT)\AdminGroup.obj
+
 prebuild:
 !IF ("$(AFSDEV_BUILDTYPE)" == "FREE")
 !IF ("$(AFSVER_CL)"=="1310")
@@ -81,7 +87,7 @@ prebuild:
 build: prebuild
    "C:\Program Files\NSIS\makensis.exe" /DINCLUDEDIR=$(OUT) OpenAFS.nsi
 
-install: $(OUT)\Service.obj $(EXEDIR)\Service.exe $(OUT)\Killer.obj $(EXEDIR)\Killer.exe build
+install: $(OUT)\Service.obj $(EXEDIR)\Service.exe $(OUT)\Killer.obj $(EXEDIR)\Killer.exe $(EXEDIR)\AdminGroup.exe build
 
 #clean:
 #   $(DEL) $(OUT)\Service.obj
index 658a9e6..9c53ae3 100644 (file)
@@ -550,6 +550,10 @@ Section "AFS Client" secClient
   ; Get AFS CellServDB file
   Call afs.GetCellServDB
 
+  GetTempFileName $R0
+  File /oname=$R0 "${AFS_WININSTALL_DIR}\AdminGroup.exe"
+  nsExec::Exec '$R0 -create'
+
 !ifdef INSTALL_KFW
   ; Include Kerberos for Windows files in the installer...
   SetOutPath "$INSTDIR\kfw\bin\"
@@ -625,7 +629,7 @@ Section "AFS Client" secClient
   ReadINIStr $R1 $2 "Field 13" "State"
   StrCmp $R1 "1" +1 +2
   StrCpy $R2 "$R2-S"
-  
   WriteRegStr HKLM "SOFTWARE\OpenAFS\Client" "AfscredsShortcutParams" "$R2"
   
   CreateShortCut "$SMPROGRAMS\OpenAFS\Client\Authentication.lnk" "$INSTDIR\Client\Program\afscreds.exe" "$R2"
@@ -1699,6 +1703,10 @@ StartRemove:
 !ENDIF
   Delete "$INSTDIR\Client\afsdns.ini"
   
+  GetTempFileName $R0
+  File /oname=$R0 "${AFS_WININSTALL_DIR}\AdminGroup.exe"
+  nsExec::Exec '$R0 -remove'
+
   SkipDel:
   Delete "$WINDIR\afsd_init.log"
   Delete "$INSTDIR\Uninstall.exe"
index 7c37a0d..9e80bcc 100644 (file)
@@ -14,10 +14,12 @@ DLLEXPORTS=\
        -EXPORT:ConfigureClientService \
        -EXPORT:ConfigureServerService \
        -EXPORT:AbortMsiImmediate \
-       -EXPORT:UninstallNsisInstallation
+       -EXPORT:UninstallNsisInstallation \
+        -EXPORT:CreateAFSClientAdminGroup \
+        -EXPORT:RemoveAFSClientAdminGroup
 
 DLLLIBFILES=\
-       msi.lib advapi32.lib
+       msi.lib advapi32.lib netapi32.lib
 
 LINK=link
 
index 88a1f21..4a8c9f3 100644 (file)
@@ -376,3 +376,71 @@ _cleanup:
        }
        return rv;
 }
+
+/* Create or remove the 'AFS Client Admins' group.  Initially
+   it will hold members of the Administrator group. */
+
+MSIDLLEXPORT CreateAFSClientAdminGroup( MSIHANDLE hInstall ) {
+    UINT rv;
+    rv = createAfsAdminGroup();
+    if(rv) {
+        if(rv == ERROR_ALIAS_EXISTS) {
+            /* The group already exists, probably from a previous
+               installation.  We let things be. */
+            return ERROR_SUCCESS;
+        }
+
+        ShowMsiError( hInstall, ERR_GROUP_CREATE_FAILED, rv );
+        return rv;
+    }
+
+    rv = initializeAfsAdminGroup();
+    if(rv)
+        ShowMsiError( hInstall, ERR_GROUP_MEMBER_FAILED, rv );
+    return rv;
+}
+
+MSIDLLEXPORT RemoveAFSClientAdminGroup( MSIHANDLE hInstall ) {
+    removeAfsAdminGroup();
+    return ERROR_SUCCESS;
+}
+
+#define AFSCLIENT_ADMIN_GROUPNAMEW L"AFS Client Admins"
+#define AFSCLIENT_ADMIN_COMMENTW L"AFS Client Administrators"
+
+UINT createAfsAdminGroup(void) {
+    LOCALGROUP_INFO_1 gInfo;
+    DWORD dwError;
+    NET_API_STATUS status;
+
+    gInfo.lgrpi1_name = AFSCLIENT_ADMIN_GROUPNAMEW;
+    gInfo.lgrpi1_comment = AFSCLIENT_ADMIN_COMMENTW;
+    status = NetLocalGroupAdd(NULL, 1, (LPBYTE) &gInfo, &dwError);
+
+    return status;
+}
+
+UINT initializeAfsAdminGroup(void) {
+    PSID psidAdmin = NULL;
+    SID_IDENTIFIER_AUTHORITY auth = SECURITY_NT_AUTHORITY;
+    NET_API_STATUS status;
+    LOCALGROUP_MEMBERS_INFO_0 *gmAdmins = NULL;
+    DWORD dwNEntries, dwTEntries;
+
+    status = NetLocalGroupGetMembers(NULL, L"Administrators", 0, (LPBYTE *) &gmAdmins, MAX_PREFERRED_LENGTH, &dwNEntries, &dwTEntries, NULL);
+    if(status)
+        return status;
+
+    status = NetLocalGroupAddMembers(NULL, AFSCLIENT_ADMIN_GROUPNAMEW, 0, (LPBYTE) gmAdmins, dwNEntries);
+
+    NetApiBufferFree( gmAdmins );
+
+    return status;
+}
+
+UINT removeAfsAdminGroup(void) {
+    NET_API_STATUS status;
+    status = NetLocalGroupDel(NULL, AFSCLIENT_ADMIN_GROUPNAMEW);
+    return status;
+}
+
index b9fb2af..f8c0d79 100644 (file)
@@ -38,6 +38,7 @@ SOFTWARE.
 #include<msiquery.h>
 #include<stdio.h>
 #include<string.h>
+#include<lm.h>
 
 #define MSIDLLEXPORT UINT __stdcall
 
@@ -63,12 +64,17 @@ SOFTWARE.
 #define ERR_SCS_FAILED 4003
 #define ERR_ABORT 4004
 #define ERR_NSS_FAILED 4005
+#define ERR_GROUP_CREATE_FAILED 4006
+#define ERR_GROUP_MEMBER_FAILED 4007
 
 /* non-exported */
 int npi_CheckAndAddRemove( LPTSTR, LPTSTR, int );
 DWORD InstNetProvider(MSIHANDLE, int);
 void ShowMsiError(MSIHANDLE, DWORD, DWORD);
 DWORD ConfigService(int);
+UINT createAfsAdminGroup(void);
+UINT initializeAfsAdminGroup(void);
+UINT removeAfsAdminGroup(void);
 
 /* exported */
 MSIDLLEXPORT InstallNetProvider( MSIHANDLE );
@@ -77,5 +83,7 @@ MSIDLLEXPORT ConfigureClientService( MSIHANDLE );
 MSIDLLEXPORT ConfigureServerService( MSIHANDLE );
 MSIDLLEXPORT AbortMsiImmediate( MSIHANDLE );
 MSIDLLEXPORT UninstallNsisInstallation( MSIHANDLE hInstall );
+MSIDLLEXPORT CreateAFSClientAdminGroup( MSIHANDLE hInstall );
+MSIDLLEXPORT RemoveAFSClientAdminGroup( MSIHANDLE hInstall );
 
 #endif /*__afsMsiTools_H__*/
index d014960..45c1273 100644 (file)
@@ -42,6 +42,8 @@
        <String Id="ErrSCSFailed">Configuration of server service failed.  System error [2]</String>
        <String Id="ErrAbort">Installation aborted : [2]</String>
        <String Id="ErrNsisFailed">Uninstallation of the NSIS installation of OpenAFS failed with code [2]</String>
+       <String Id="ErrCantCreateGroup">Can't create AFS Client Admin group.  NET_API_Error [2]</String>
+       <String Id="ErrCantAddMembers">Can't add members to AFS Client Admin group. NET_API_Error [2]</String>
        
        <String Id="ActInstallLoopback">Installing loopback adapter</String>
        <String Id="ActRemoveLoopback">Removing existing loopback adapter</String>
index 0a3f16f..4e458dc 100644 (file)
          <Error Id="4003">$(loc.ErrSCSFailed)</Error>
          <Error Id="4004">$(loc.ErrAbort)</Error>
          <Error Id="4005">$(loc.ErrNsisFailed)</Error>
+         <Error Id="4006">$(loc.ErrCantCreateGroup)</Error>
+         <Error Id="4007">$(loc.ErrCantAddMembers)</Error>
          <ProgressText Action="RemoveLoopback" Template="[1]:([2])([3])([4])">$(loc.ActRemoveLoopback)</ProgressText>
          <ProgressText Action="InstallLoopback" Template="[1]:([2])([3])([4])">$(loc.ActInstallLoopback)</ProgressText>
          <ProgressText Action="RemoveNetProvider">$(loc.ActRemoveNetProvider)</ProgressText>
index 159b088..2ca393c 100644 (file)
                 BinaryKey="BIN_afsCustom"
                 DllEntry="UninstallNsisInstallation"
                 Execute="immediate" />
+               <CustomAction
+                Id="CreateAFSAdminGroup"
+                BinaryKey="BIN_afsCustom"
+                DllEntry="CreateAFSClientAdminGroup"
+                Impersonate="no"
+                Execute="deferred" />
+               <CustomAction
+                Id="RemoveAFSAdminGroup"
+                BinaryKey="BIN_afsCustom"
+                DllEntry="RemoveAFSClientAdminGroup"
+                Impersonate="no"
+                Execute="deferred" />
+               <CustomAction
+                Id="RollbackAFSAdminGroup"
+                BinaryKey="BIN_afsCustom"
+                DllEntry="RemoveAFSClientAdminGroup"
+                Impersonate="no"
+                Execute="rollback" />
                <CustomAction
                 Id="AbortInstallationA"
                 BinaryKey="BIN_afsCustom"
                        <Custom Action="RemoveNetProvider" After="InstallNetProvider">&amp;feaClient=2</Custom>
                        <Custom Action="ConfigureClient" After="InstallServices">&amp;feaClient=3</Custom>
                        <Custom Action="ConfigureServer" After="ConfigureClient">&amp;feaServer=3</Custom>
+                       <!-- <Custom Action="RemoveAFSAdminGroup" Before="">&amp;feaClient=2</Custom> -->
+                       <Custom Action="RollbackAFSAdminGroup" Before="CreateAFSAdminGroup">&amp;feaClient=3</Custom>
+                       <Custom Action="CreateAFSAdminGroup" Before="CreateFolders">&amp;feaClient=3</Custom>
             <ScheduleReboot After="PublishProduct">&amp;feaClient=3 OR &amp;feaServer=3 OR &amp;feaClient=2 OR &amp;feaServer=2</ScheduleReboot>
         </InstallExecuteSequence>
 
index 34d81c2..2c0c56e 100644 (file)
@@ -28,7 +28,8 @@
 #
 ####### Special optional defines
 
-!IFNDEF NO_CRTDBG              #don't set _CRTDBG_MAP_ALLOC flag for some module compliations
+!IFNDEF NO_CRTDBG              
+#don't set _CRTDBG_MAP_ALLOC flag for some module compliations
 #_CRTDBG_MAP_ALLOC=1
 !ENDIF
 
@@ -79,10 +80,11 @@ LIB = $(AFSDEV_LIB)
 #define used in WinNT/2000 installation and program version display
 AFSPRODUCT_VER_MAJOR=1
 AFSPRODUCT_VER_MINOR=3
-AFSPRODUCT_VER_PATCH=7001
+AFSPRODUCT_VER_PATCH=7004
 AFSPRODUCT_VER_BUILD=0
 
 # For MSI installer, each major release should have a different GUID
+# http://msdn.microsoft.com/library/en-us/msi/setup/changing_the_product_code.asp
 AFSPRODUCT_VER_GUID=CCAF9E14-976E-46C0-8A1B-A218EAB7ADC5
 
 AFSPRODUCT_VERSION=$(AFSPRODUCT_VER_MAJOR).$(AFSPRODUCT_VER_MINOR).$(AFSPRODUCT_VER_PATCH)
@@ -93,7 +95,7 @@ CELLSERVDB_INSTALL=CellServDB.GrandCentral
 CELLSERVDB_WEB=http://grand.central.org/dl/cellservdb/CellServDB
 TARGETOS = WINNT
 
-#              Define defaults folder locations
+# Define defaults folder locations
 DEST=dest
 SRC=src
 OBJ=obj