From: Jeffrey Altman Date: Thu, 4 Aug 2005 17:03:50 +0000 (+0000) Subject: windows-pioctl-update-20050804 X-Git-Tag: openafs-devel-1_5_0~405 X-Git-Url: https://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=81b0f9cf1d0335a1e2f8ae897ba9566c1e4962e3 windows-pioctl-update-20050804 change "fs wscell" to report the registry configured cell name when using freelance mode. change "fs mkmount|rmmount" to require membership in AFS Client Admins group when freelance mode is being used change "symlink make|remove" to require membership in AFS Client Admins group when freelance mode is being used Move some smb init debug messages to afsd_init.log --- diff --git a/src/WINNT/afsd/afsd_init.c b/src/WINNT/afsd/afsd_init.c index 37189ec..03dacb7 100644 --- a/src/WINNT/afsd/afsd_init.c +++ b/src/WINNT/afsd/afsd_init.c @@ -139,7 +139,7 @@ afsi_start() char wd[256]; char t[100], u[100], *p, *path; int zilch; - int code; + DWORD code; DWORD dwLow, dwHigh; HKEY parmKey; DWORD dummyLen; diff --git a/src/WINNT/afsd/cm_ioctl.c b/src/WINNT/afsd/cm_ioctl.c index 7a09cb6..1d09f9c 100644 --- a/src/WINNT/afsd/cm_ioctl.c +++ b/src/WINNT/afsd/cm_ioctl.c @@ -1214,15 +1214,16 @@ long cm_IoctlGetWsCell(smb_ioctl_t *ioctlp, cm_user_t *userp) long code = 0; if (cm_freelanceEnabled) { - StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root"); - ioctlp->outDatap += strlen(ioctlp->outDatap) +1; + if (cm_GetRootCellName(ioctlp->outDatap)) + StringCbCopyA(ioctlp->outDatap, 999999, "Freelance.Local.Root"); + ioctlp->outDatap += strlen(ioctlp->outDatap) +1; } else if (cm_data.rootCellp) { /* return the default cellname to the caller */ StringCbCopyA(ioctlp->outDatap, 999999, cm_data.rootCellp->name); ioctlp->outDatap += strlen(ioctlp->outDatap) +1; } else { /* if we don't know our default cell, return failure */ - code = CM_ERROR_NOSUCHCELL; + code = CM_ERROR_NOSUCHCELL; } return code; diff --git a/src/WINNT/afsd/fs.c b/src/WINNT/afsd/fs.c index eb7bff8..5c7d0ad 100644 --- a/src/WINNT/afsd/fs.c +++ b/src/WINNT/afsd/fs.c @@ -271,6 +271,22 @@ InAFS(char *apath) return 1; } +static int +IsFreelanceRoot(char *apath) +{ + struct ViceIoctl blob; + afs_int32 code; + + blob.in_size = 0; + blob.out_size = MAXSIZE; + blob.out = space; + + code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1); + if (code == 0) + return !strcmp("Freelance.Local.Root",space); + return 1; /* assume it is because it is more restrictive that way */ +} + /* return a static pointer to a buffer */ static char * Parent(char *apath) @@ -690,9 +706,27 @@ AclToString(struct Acl *acl) return mydata; } +static DWORD IsFreelance(void) +{ + HKEY parmKey; + DWORD code; + DWORD dummyLen; + DWORD enabled = 0; + + code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY, + 0, KEY_QUERY_VALUE, &parmKey); + if (code == ERROR_SUCCESS) { + dummyLen = sizeof(cm_freelanceEnabled); + code = RegQueryValueEx(parmKey, "FreelanceClient", NULL, NULL, + (BYTE *) &enabled, &dummyLen); + RegCloseKey (parmKey); + } + return enabled; +} + #define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins" -BOOL IsAdmin (void) +static BOOL IsAdmin (void) { static BOOL fAdmin = FALSE; static BOOL fTested = FALSE; @@ -1750,6 +1784,7 @@ MakeMountCmd(struct cmd_syndesc *as, char *arock) struct vldbentry vldbEntry; #endif /* not WIN32 */ struct ViceIoctl blob; + char * parent; /* @@ -1786,11 +1821,17 @@ MakeMountCmd(struct cmd_syndesc *as, char *arock) volName = ++tmpName; } - if (!InAFS(Parent(as->parms[0].items->data))) { + parent = Parent(as->parms[0].items->data); + if (!InAFS(parent)) { fprintf(stderr,"%s: mount points must be created within the AFS file system\n", pn); return 1; } + if ( IsFreelanceRoot(parent) && !IsAdmin() ) { + fprintf(stderr,"%s: Only AFS Client Administrators may alter the root.afs volume\n", pn); + return 1; + } + if (!cellName) { blob.in_size = 0; blob.out_size = MAXSIZE; @@ -1901,7 +1942,14 @@ RemoveMountCmd(struct cmd_syndesc *as, char *arock) { error = 1; continue; /* don't bother trying */ } - blob.out_size = 0; + + if ( IsFreelanceRoot(Parent(tp)) && !IsAdmin() ) { + fprintf(stderr,"%s: Only AFS Client Administrators may alter the root.afs volume\n", pn); + error = 1; + continue; /* skip */ + } + + blob.out_size = 0; blob.in = tp; blob.in_size = strlen(tp)+1; code = pioctl(tbuffer, VIOC_AFS_DELETE_MT_PT, &blob, 0); diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index 4892c2a..5042c51 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -7748,7 +7748,7 @@ void smb_NetbiosInit() ncbp->ncb_length = sizeof(lana_list); code = Netbios(ncbp); if (code != 0) { - osi_Log1(smb_logp, "Netbios NCBENUM error code %d", code); + afsi_log("Netbios NCBENUM error code %d", code); osi_panic(s, __FILE__, __LINE__); } } @@ -7769,10 +7769,10 @@ void smb_NetbiosInit() if (code == 0) code = ncbp->ncb_retcode; if (code != 0) { - osi_Log2(smb_logp, "Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code); + afsi_log("Netbios NCBRESET lana %d error code %d", lana_list.lana[i], code); lana_list.lana[i] = 255; /* invalid lana */ } else { - osi_Log1(smb_logp, "Netbios NCBRESET lana %d succeeded", lana_list.lana[i]); + afsi_log("Netbios NCBRESET lana %d succeeded", lana_list.lana[i]); } } #else @@ -7794,7 +7794,7 @@ void smb_NetbiosInit() len=lstrlen(smb_localNamep); memset(smb_sharename,' ',NCBNAMSZ); memcpy(smb_sharename,smb_localNamep,len); - osi_Log1(smb_logp, "lana_list.length %d", lana_list.length); + afsi_log("lana_list.length %d", lana_list.length); /* Keep the name so we can unregister it later */ for (l = 0; l < lana_list.length; l++) { @@ -7809,18 +7809,18 @@ void smb_NetbiosInit() code = Netbios(ncbp, dos_ncb); #endif /* !DJGPP */ - osi_Log4(smb_logp, "Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d", + afsi_log("Netbios NCBADDNAME lana=%d code=%d retcode=%d complete=%d", lana, code, ncbp->ncb_retcode, ncbp->ncb_cmd_cplt); { char name[NCBNAMSZ+1]; name[NCBNAMSZ]=0; memcpy(name,ncbp->ncb_name,NCBNAMSZ); - osi_Log1(smb_logp, "Netbios NCBADDNAME added new name >%s<",osi_LogSaveString(smb_logp, name)); + afsi_log("Netbios NCBADDNAME added new name >%s<",name); } if (code == 0) code = ncbp->ncb_retcode; if (code == 0) { - osi_Log1(smb_logp, "Netbios NCBADDNAME succeeded on lana %d\n", lana); + afsi_log("Netbios NCBADDNAME succeeded on lana %d\n", lana); #ifdef DJGPP /* we only use one LANA with djgpp */ lana_list.lana[0] = lana; @@ -7828,13 +7828,13 @@ void smb_NetbiosInit() #endif } else { - osi_Log2(smb_logp, "Netbios NCBADDNAME lana %d error code %d", lana, code); + afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code); if (code == NRC_BRIDGE) { /* invalid LANA num */ lana_list.lana[l] = 255; continue; } else if (code == NRC_DUPNAME) { - osi_Log0(smb_logp, "Name already exists; try to delete it"); + afsi_log("Name already exists; try to delete it"); memset(ncbp, 0, sizeof(*ncbp)); ncbp->ncb_command = NCBDELNAME; memcpy(ncbp->ncb_name,smb_sharename,NCBNAMSZ); @@ -7847,7 +7847,7 @@ void smb_NetbiosInit() if (code == 0) code = ncbp->ncb_retcode; else { - osi_Log2(smb_logp, "Netbios NCBDELNAME lana %d error code %d\n", lana, code); + afsi_log("Netbios NCBDELNAME lana %d error code %d\n", lana, code); } if (code != 0 || delname_tried) { lana_list.lana[l] = 255; @@ -7861,7 +7861,7 @@ void smb_NetbiosInit() } } else { - osi_Log2(smb_logp, "Netbios NCBADDNAME lana %d error code %d", lana, code); + afsi_log("Netbios NCBADDNAME lana %d error code %d", lana, code); lana_list.lana[l] = 255; /* invalid lana */ osi_panic(s, __FILE__, __LINE__); } @@ -8192,11 +8192,10 @@ void smb_Init(osi_log_t *logp, char *snamep, int useV3, int LANadapt, sprintf(message,"MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x", nts, ntsEx); OutputDebugString(message); - osi_Log2(smb_logp,"MsV1_0SetProcessOption failure: nts 0x%x ntsEx 0x%x", - nts, ntsEx); + afsi_log(message); } else { OutputDebugString("MsV1_0SetProcessOption success"); - osi_Log0(smb_logp,"MsV1_0SetProcessOption success"); + afsi_log("MsV1_0SetProcessOption success"); } /* END - code from Larry */ diff --git a/src/WINNT/afsd/symlink.c b/src/WINNT/afsd/symlink.c index 0b7322a..4ab4cda 100644 --- a/src/WINNT/afsd/symlink.c +++ b/src/WINNT/afsd/symlink.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -57,8 +58,8 @@ foldcmp (a, b) } /* this function returns TRUE (1) if the file is in AFS, otherwise false (0) */ -static int InAFS(apath) -register char *apath; { +static int InAFS(register char *apath) +{ struct ViceIoctl blob; register afs_int32 code; @@ -68,11 +69,167 @@ register char *apath; { code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1); if (code) { - if ((errno == EINVAL) || (errno == ENOENT)) return 0; + if ((errno == EINVAL) || (errno == ENOENT)) + return 0; } return 1; } +static int +IsFreelanceRoot(char *apath) +{ + struct ViceIoctl blob; + afs_int32 code; + + blob.in_size = 0; + blob.out_size = MAXSIZE; + blob.out = space; + + code = pioctl(apath, VIOC_FILE_CELL_NAME, &blob, 1); + if (code == 0) + return !strcmp("Freelance.Local.Root",space); + return 1; /* assume it is because it is more restrictive that way */ +} + +#define AFSCLIENT_ADMIN_GROUPNAME "AFS Client Admins" + +static BOOL IsAdmin (void) +{ + 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; + } + + 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); + assert(psidAdmin); + pszRefDomain = (char *)malloc(dwSize2); + assert(pszRefDomain); + + 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)) + { + + if (!CheckTokenMembership(hToken, psidAdmin, &fAdmin)) { + /* 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); + + pGroups = (PTOKEN_GROUPS)malloc(dwSize); + assert(pGroups); + + /* 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 do not have permission because we were not explicitly listed + * in the Admin Client Group let's see if we are the SYSTEM account + */ + if (!fAdmin) { + PTOKEN_USER pTokenUser; + SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_NT_AUTHORITY; + PSID pSidLocalSystem = 0; + DWORD gle; + + GetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize); + + pTokenUser = (PTOKEN_USER)malloc(dwSize); + assert(pTokenUser); + + if (!GetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize)) + gle = GetLastError(); + + if (AllocateAndInitializeSid( &SIDAuth, 1, + SECURITY_LOCAL_SYSTEM_RID, + 0, 0, 0, 0, 0, 0, 0, + &pSidLocalSystem)) + { + if (EqualSid(pTokenUser->User.Sid, pSidLocalSystem)) { + fAdmin = TRUE; + } + + FreeSid(pSidLocalSystem); + } + + if ( pTokenUser ) + free(pTokenUser); + } + } + } + + free(psidAdmin); + free(pszRefDomain); + + fTested = TRUE; + } + + return fAdmin; +} + /* return a static pointer to a buffer */ static char *Parent(apath) char *apath; { @@ -230,12 +387,20 @@ static MakeLinkCmd(as) register struct cmd_syndesc *as; { register afs_int32 code; struct ViceIoctl blob; + char * parent; - if (!InAFS(Parent(as->parms[0].items->data))) { + parent = Parent(as->parms[0].items->data); + + if (!InAFS(parent)) { fprintf(stderr,"%s: symlinks must be created within the AFS file system\n", pn); return 1; } + if ( IsFreelanceRoot(parent) && !IsAdmin() ) { + fprintf(stderr,"%s: Only AFS Client Administrators may alter the root.afs volume\n", pn); + return 1; + } + strcpy(space, as->parms[1].items->data); #ifdef WIN32 /* create symlink with a special pioctl for Windows NT, since it doesn't @@ -299,12 +464,19 @@ register struct cmd_syndesc *as; { code = pioctl(tbuffer, VIOC_LISTSYMLINK, &blob, 0); if (code) { if (errno == EINVAL) - fprintf(stderr,"fs: '%s' is not a symlink.\n", ti->data); + fprintf(stderr,"symlink: '%s' is not a symlink.\n", ti->data); else { Die(errno, ti->data); } continue; /* don't bother trying */ } + + if ( IsFreelanceRoot(Parent(tp)) && !IsAdmin() ) { + fprintf(stderr,"symlink: Only AFS Client Administrators may alter the root.afs volume\n"); + code = 1; + continue; /* skip */ + } + blob.out_size = 0; blob.in = tp; blob.in_size = strlen(tp)+1; @@ -312,7 +484,6 @@ register struct cmd_syndesc *as; { if (code) { Die(errno, ti->data); } - } return code; }