📄 security.c
字号:
return FALSE; /* We've successfully collected all the information needed for this * property access rule. Now record it in a PropertyAccessRec. */ size = sizeof(PropertyAccessRec); /* If there is a property value string, allocate space for it * right after the PropertyAccessRec. */ if (mustHaveValue) size += strlen(mustHaveValue) + 1; pacl = (PropertyAccessPtr)Xalloc(size); if (!pacl) return FALSE; pacl->name = MakeAtom(propname, strlen(propname), TRUE); if (pacl->name == BAD_RESOURCE) { Xfree(pacl); return FALSE; } if (mustHaveProperty) { pacl->mustHaveProperty = MakeAtom(mustHaveProperty, strlen(mustHaveProperty), TRUE); if (pacl->mustHaveProperty == BAD_RESOURCE) { Xfree(pacl); return FALSE; } } else pacl->mustHaveProperty = 0; if (mustHaveValue) { pacl->mustHaveValue = (char *)(pacl + 1); strcpy(pacl->mustHaveValue, mustHaveValue); } else pacl->mustHaveValue = NULL; SecurityMaxPropertyName = max(SecurityMaxPropertyName, pacl->name); pacl->windowRestriction = windowRestriction; pacl->readAction = readAction; pacl->writeAction = writeAction; pacl->destroyAction = destroyAction; /* link the new rule into the list of rules in order of increasing * property name (atom) value to make searching easier */ for (prev = NULL, cur = PropertyAccessList; cur && cur->name <= pacl->name; prev = cur, cur = cur->next) ; if (!prev) { pacl->next = cur; PropertyAccessList = pacl; } else { prev->next = pacl; pacl->next = cur; } return TRUE;} /* SecurityParsePropertyAccessRule */static char **SecurityPolicyStrings = NULL;static int nSecurityPolicyStrings = 0;static BoolSecurityParseSitePolicy(p) char *p;{ char *policyStr = SecurityParseString(&p); char *copyPolicyStr; char **newStrings; if (!policyStr) return FALSE; copyPolicyStr = (char *)Xalloc(strlen(policyStr) + 1); if (!copyPolicyStr) return TRUE; strcpy(copyPolicyStr, policyStr); newStrings = (char **)Xrealloc(SecurityPolicyStrings, sizeof (char *) * (nSecurityPolicyStrings + 1)); if (!newStrings) { Xfree(copyPolicyStr); return TRUE; } SecurityPolicyStrings = newStrings; SecurityPolicyStrings[nSecurityPolicyStrings++] = copyPolicyStr;} /* SecurityParseSitePolicy */char **SecurityGetSitePolicyStrings(n) int *n;{ *n = nSecurityPolicyStrings; return SecurityPolicyStrings;} /* SecurityGetSitePolicyStrings */static voidSecurityFreeSitePolicyStrings(){ if (SecurityPolicyStrings) { assert(nSecurityPolicyStrings); while (nSecurityPolicyStrings--) { Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]); } Xfree(SecurityPolicyStrings); SecurityPolicyStrings = NULL; nSecurityPolicyStrings = 0; }} /* SecurityFreeSitePolicyStrings */static voidSecurityLoadPropertyAccessList(){ FILE *f; int lineNumber = 0; SecurityMaxPropertyName = 0; if (!SecurityPolicyFile) return;#ifndef __EMX__ f = fopen(SecurityPolicyFile, "r");#else f = fopen((char*)__XOS2RedirRoot(SecurityPolicyFile), "r");#endif if (!f) { ErrorF("error opening security policy file %s\n", SecurityPolicyFile); return; } while (!feof(f)) { char buf[200]; Bool validLine; char *p; if (!(p = fgets(buf, sizeof(buf), f))) break; lineNumber++; /* if first line, check version number */ if (lineNumber == 1) { char *v = SecurityParseString(&p); if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0) { ErrorF("%s: invalid security policy file version, ignoring file\n", SecurityPolicyFile); break; } validLine = TRUE; } else { switch (SecurityParseKeyword(&p)) { case SecurityKeywordComment: validLine = TRUE; break; case SecurityKeywordProperty: validLine = SecurityParsePropertyAccessRule(p); break; case SecurityKeywordSitePolicy: validLine = SecurityParseSitePolicy(p); break; default: validLine = (*p == '\0'); /* blank lines OK, others not */ break; } } if (!validLine) ErrorF("Line %d of %s invalid, ignoring\n", lineNumber, SecurityPolicyFile); } /* end while more input */#ifdef PROPDEBUG { PropertyAccessPtr pacl; char *op = "aie"; for (pacl = PropertyAccessList; pacl; pacl = pacl->next) { ErrorF("property %s ", NameForAtom(pacl->name)); switch (pacl->windowRestriction) { case SecurityAnyWindow: ErrorF("any "); break; case SecurityRootWindow: ErrorF("root "); break; case SecurityWindowWithProperty: { ErrorF("%s ", NameForAtom(pacl->mustHaveProperty)); if (pacl->mustHaveValue) ErrorF(" = \"%s\" ", pacl->mustHaveValue); } break; } ErrorF("%cr %cw %cd\n", op[pacl->readAction], op[pacl->writeAction], op[pacl->destroyAction]); } }#endif /* PROPDEBUG */ fclose(f);} /* SecurityLoadPropertyAccessList */static BoolSecurityMatchString(ws, cs) char *ws; char *cs;{ while (*ws && *cs) { if (*ws == '*') { Bool match = FALSE; ws++; while (!(match = SecurityMatchString(ws, cs)) && *cs) { cs++; } return match; } else if (*ws == *cs) { ws++; cs++; } else break; } return ( ( (*ws == '\0') || ((*ws == '*') && *(ws+1) == '\0') ) && (*cs == '\0') );} /* SecurityMatchString */#ifdef PROPDEBUG#include <sys/types.h>#include <sys/stat.h>#endifcharSecurityCheckPropertyAccess(client, pWin, propertyName, access_mode) ClientPtr client; WindowPtr pWin; ATOM propertyName; Mask access_mode;{ PropertyAccessPtr pacl; char action = SecurityDefaultAction; /* if client trusted or window untrusted, allow operation */ if ( (client->trustLevel == XSecurityClientTrusted) || (wClient(pWin)->trustLevel != XSecurityClientTrusted) ) return SecurityAllowOperation;#ifdef PROPDEBUG /* For testing, it's more convenient if the property rules file gets * reloaded whenever it changes, so we can rapidly try things without * having to reset the server. */ { struct stat buf; static time_t lastmod = 0; int ret = stat(SecurityPolicyFile , &buf); if ( (ret == 0) && (buf.st_mtime > lastmod) ) { ErrorF("reloading property rules\n"); SecurityFreePropertyAccessList(); SecurityLoadPropertyAccessList(); lastmod = buf.st_mtime; } }#endif /* If the property atom is bigger than any atoms on the list, * we know we won't find it, so don't even bother looking. */ if (propertyName <= SecurityMaxPropertyName) { /* untrusted client operating on trusted window; see if it's allowed */ for (pacl = PropertyAccessList; pacl; pacl = pacl->next) { if (pacl->name < propertyName) continue; if (pacl->name > propertyName) break; /* pacl->name == propertyName, so see if it applies to this window */ switch (pacl->windowRestriction) { case SecurityAnyWindow: /* always applies */ break; case SecurityRootWindow: { /* if not a root window, this rule doesn't apply */ if (pWin->parent) continue; } break; case SecurityWindowWithProperty: { PropertyPtr pProp = wUserProps (pWin); Bool match = FALSE; char *p; char *pEndData; while (pProp) { if (pProp->propertyName == pacl->mustHaveProperty) break; pProp = pProp->next; } if (!pProp) continue; if (!pacl->mustHaveValue) break; if (pProp->type != XA_STRING || pProp->format != 8) continue; p = pProp->data; pEndData = ((char *)pProp->data) + pProp->size; while (!match && p < pEndData) { if (SecurityMatchString(pacl->mustHaveValue, p)) match = TRUE; else { /* skip to the next string */ while (*p++ && p < pEndData) ; } } if (!match) continue; } break; /* end case SecurityWindowWithProperty */ } /* end switch on windowRestriction */ /* If we get here, the property access rule pacl applies. * If pacl doesn't apply, something above should have * executed a continue, which will skip the follwing code. */ action = SecurityAllowOperation; if (access_mode & SecurityReadAccess) action = max(action, pacl->readAction); if (access_mode & SecurityWriteAccess) action = max(action, pacl->writeAction); if (access_mode & SecurityDestroyAccess) action = max(action, pacl->destroyAction); break; } /* end for each pacl */ } /* end if propertyName <= SecurityMaxPropertyName */ if (SecurityAllowOperation != action) { /* audit the access violation */ int cid = CLIENT_ID(pWin->drawable.id); int reqtype = ((xReq *)client->requestBuffer)->reqType; char *actionstr = (SecurityIgnoreOperation == action) ? "ignored" : "error"; SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n", client->index, reqtype, pWin->drawable.id, NameForAtom(propertyName), propertyName, cid, actionstr); } return action;} /* SecurityCheckPropertyAccess *//* SecurityResetProc * * Arguments: * extEntry is the extension information for the security extension. * * Returns: nothing. * * Side Effects: * Performs any cleanup needed by Security at server shutdown time. */static voidSecurityResetProc(extEntry) ExtensionEntry *extEntry;{ SecurityFreePropertyAccessList(); SecurityFreeSitePolicyStrings();} /* SecurityResetProc */intXSecurityOptions(argc, argv, i) int argc; char **argv; int i;{ if (strcmp(argv[i], "-sp") == 0) { if (i < argc) SecurityPolicyFile = argv[++i]; return (i + 1); } return (i);} /* XSecurityOptions *//* SecurityExtensionInit * * Arguments: none. * * Returns: nothing. * * Side Effects: * Enables the Security extension if possible. */voidSecurityExtensionInit(){ ExtensionEntry *extEntry; int i; SecurityAuthorizationResType = CreateNewResourceType(SecurityDeleteAuthorization); RTEventClient = CreateNewResourceType( SecurityDeleteAuthorizationEventClient); if (!SecurityAuthorizationResType || !RTEventClient) return; RTEventClient |= RC_NEVERRETAIN; if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL)) return; extEntry = AddExtension(SECURITY_EXTENSION_NAME, XSecurityNumberEvents, XSecurityNumberErrors, ProcSecurityDispatch, SProcSecurityDispatch, SecurityResetProc, StandardMinorOpcode); SecurityErrorBase = extEntry->errorBase; SecurityEventBase = extEntry->eventBase; EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] = SwapSecurityAuthorizationRevokedEvent; /* initialize untrusted proc vectors */ for (i = 0; i < 128; i++) { UntrustedProcVector[i] = ProcVector[i]; SwappedUntrustedProcVector[i] = SwappedProcVector[i]; } /* make sure insecure extensions are not allowed */ for (i = 128; i < 256; i++) { if (!UntrustedProcVector[i]) { UntrustedProcVector[i] = ProcBadRequest; SwappedUntrustedProcVector[i] = ProcBadRequest; } } SecurityLoadPropertyAccessList();} /* SecurityExtensionInit */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -