/** * @brief * add_to_administrators_group: returns 0 if 'dnamew\unamew' has been added * to local "Administrators" group; 1 otherwise. * * @param[in] dnamew - account name * @param[in] unamew - A pointer to a constant string that specifies * the name of the user account for which to set * information. * * @return int * @retval 0 : 'dnamew\unamew' has been added to local "Administrators" group. * @retval 1 : 'dnamew\unamew' could not add to local "Administrators" group. */ int add_to_administrators_group(wchar_t *dnamew, wchar_t *unamew) { SID *gsid = NULL; char *gname = NULL; /* special group to add service account to */ wchar_t full_unamew[PBS_MAXHOSTNAME+UNLEN+2]; /* domain\user\0 */ int ret_val = 1; gsid = create_administrators_sid(); if (gsid && (gname=getgrpname(gsid))) { LOCALGROUP_MEMBERS_INFO_3 member; NET_API_STATUS nstatus; wchar_t gnamew[GNLEN+1]; mbstowcs(gnamew, gname, GNLEN+1); #if _MSC_VER >= 1400 swprintf(full_unamew, PBS_MAXHOSTNAME+UNLEN+2, L"%s\\%s", dnamew, unamew); #else swprintf(full_unamew, L"%s\\%s", dnamew, unamew); #endif member.lgrmi3_domainandname = (wchar_t *)full_unamew; if (for_info_only) nstatus = NERR_Success; else nstatus=NetLocalGroupAddMembers(NULL, gnamew, 3, (LPBYTE)&member, 1); if( (nstatus == NERR_Success) || \ (nstatus == ERROR_MEMBER_IN_ALIAS) ) { printf("%s %S to group \"%S\"\n", (for_info_only?"Adding":"Added"), full_unamew, gnamew); ret_val = 0; } else { fprintf(stderr, "Failed to add %S to group \"%S\": error status =%d\n", full_unamew, gnamew, nstatus); } } if (strlen(winlog_buffer) > 0) { /* any error in getdefgrpname() */ fprintf(stderr, "%s\n", winlog_buffer); } if (gsid) FreeSid(gsid); else fprintf(stderr, "Failed to add %S\\%S to Administrators group: bad SID\n", dnamew, unamew); if (gname) (void)free(gname); else fprintf(stderr, "Failed to get Administrators's actual group name\n"); return (ret_val); }
/** * @brief * perm_granted_admin_and_name: returns 0 if permission mask in 'disallow' has * been granted to only admin-type of accounts and 'owner'. 'owner' can be * set to NULL. Otherwise, it will return the values EPERM or EACCESS with * error message returned in 'errmsg'. */ int perm_granted_admin_and_owner(char *path, int disallow, char *owner, char *errmsg) { int rc; DWORD i, j; SID *powner = NULL; char *powner_s = NULL; ACL *pdacl = NULL; SECURITY_DESCRIPTOR *psd = NULL; ACL_SIZE_INFORMATION sizeInfo; ACCESS_ALLOWED_ACE *pace; int violate = 0; struct accessinfo *allowed = NULL; struct accessinfo *denied = NULL; int mask; char *name; SID *esid = getusersid("Everyone"); if (GetNamedSecurityInfo(path, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION|DACL_SECURITY_INFORMATION, &powner, 0, &pdacl, 0, &psd) != ERROR_SUCCESS) { errno = GetLastError(); rc = errno; sprintf(errmsg, "GetNameSecurityInfo on file %s failed", path); goto chkerr; } /* is owner SID a privilege user? */ powner_s = getusername(powner); if (powner_s == NULL) powner_s = getgrpname(powner); if (powner_s != NULL) { if ( !sidIsAdminPrivilege(powner) || \ ( (owner != NULL) && strcmp(owner, powner_s) != 0 ) ) { rc = EPERM; sprintf(errmsg, "File %s not owned by user %s or an admin-type user!", path, owner); goto chkerr; } } /* make sure perm mask granted only to privilege groups or the special 'owner' */ GetAclInformation(pdacl, &sizeInfo, sizeof(sizeInfo), AclSizeInformation); allowed = (struct accessinfo *)malloc(sizeof(struct accessinfo)*sizeInfo.AceCount); denied = (struct accessinfo *)malloc(sizeof(struct accessinfo)*sizeInfo.AceCount); if (allowed == NULL || denied == NULL) { rc = errno; strcpy(errmsg, "malloc of allowed or denied struct failed!"); goto chkerr; } accessinfo_init(allowed, sizeInfo.AceCount); accessinfo_init(denied, sizeInfo.AceCount); for (i=0; i < sizeInfo.AceCount; i++) { GetAce(pdacl, i, (void **)&pace); name = getgrpname_full((SID *)&pace->SidStart); if (name == NULL) name = getusername((SID *)&pace->SidStart); /* later, we need to also check denied access which */ /* overrides allowed access. */ if ( pace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE &&\ (mask=(pace->Mask & disallow)) && \ ( EqualSid((SID *)&pace->SidStart, esid) || \ sid2rid((SID *)&pace->SidStart) != \ SECURITY_CREATOR_OWNER_RID ) && \ (!sidIsAdminPrivilege( (SID *)&pace->SidStart)) || \ ((owner != NULL) && strcmp(name, owner) != 0) ) { (void)accessinfo_add(allowed, sizeInfo.AceCount, name, (mask & 0xFFFF)); } else if (pace->Header.AceType == ACCESS_DENIED_ACE_TYPE) { (void)accessinfo_add(denied, sizeInfo.AceCount, name, (pace->Mask & 0xFFFF)); } else { if (name) { (void)free(name); } } } /* validate */ for (i=0; i < sizeInfo.AceCount; i++) { for (j=0; j < sizeInfo.AceCount; j++) { if( allowed[i].group == NULL || \ denied[j].group == NULL ) continue; if (strcmp(allowed[i].group, denied[j].group) == 0) allowed[i].mask &= ~denied[j].mask; /* unset the denied mask from allowed */ } } if (!accessinfo_mask_allzero(allowed, sizeInfo.AceCount)) { rc = EACCES; sprintf(errmsg, "File %s has following disallowed perm masks: ", path); strcat(errmsg, accessinfo_values(allowed, sizeInfo.AceCount)); goto chkerr; } rc = 0; chkerr: if (powner_s)(void)free(powner_s); /* NOTE: powner and pdacl hang off of psd, so a free of psd would */ /* automatically free them */ if (psd) LocalFree(psd); if (allowed) accessinfo_free(allowed, sizeInfo.AceCount); if (denied) accessinfo_free(denied, sizeInfo.AceCount); if (esid) LocalFree(esid); return (rc); }