📄 security.cc
字号:
__seterrno (); debug_printf ("Loading NtCreateToken failed."); } else { /* Set security descriptor and primary group */ psa = __sec_user (sa_buf, usersid, TRUE); if (psa->lpSecurityDescriptor && !SetSecurityDescriptorGroup ((PSECURITY_DESCRIPTOR) psa->lpSecurityDescriptor, special_pgrp ? new_groups.pgsid : well_known_null_sid, FALSE)) debug_printf ("SetSecurityDescriptorGroup %E"); /* Convert to primary token. */ if (!DuplicateTokenEx (token, MAXIMUM_ALLOWED, psa, SecurityImpersonation, TokenPrimary, &primary_token)) { __seterrno (); debug_printf ("DuplicateTokenEx %E"); } }out: if (old_priv_state >= 0) set_process_privilege (SE_CREATE_TOKEN_NAME, old_priv_state); if (token != INVALID_HANDLE_VALUE) CloseHandle (token); if (privs) free (privs); if (my_tok_gsids) free (my_tok_gsids); close_local_policy (lsa); debug_printf ("%d = create_token ()", primary_token); return primary_token;}int subauth_id = 255;HANDLEsubauth (struct passwd *pw){ LSA_STRING name; HANDLE lsa_hdl; LSA_OPERATIONAL_MODE sec_mode; NTSTATUS ret, ret2; ULONG package_id, size; struct { LSA_STRING str; CHAR buf[16]; } origin; struct { MSV1_0_LM20_LOGON auth; WCHAR dombuf[INTERNET_MAX_HOST_NAME_LENGTH + 1]; WCHAR usrbuf[UNLEN + 1]; WCHAR wkstbuf[1]; CHAR authinf1[1]; CHAR authinf2[1]; } subbuf; TOKEN_SOURCE ts; PMSV1_0_LM20_LOGON_PROFILE profile; LUID luid; QUOTA_LIMITS quota; char nt_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; char nt_user[UNLEN + 1]; SECURITY_ATTRIBUTES sa = { sizeof sa, NULL, TRUE }; HANDLE user_token = INVALID_HANDLE_VALUE; HANDLE primary_token = INVALID_HANDLE_VALUE; int old_tcb_state; if ((old_tcb_state = set_process_privilege (SE_TCB_NAME)) < 0) return INVALID_HANDLE_VALUE; /* Register as logon process. */ str2lsa (name, "Cygwin"); SetLastError (0); ret = LsaRegisterLogonProcess (&name, &lsa_hdl, &sec_mode); if (ret != STATUS_SUCCESS) { debug_printf ("LsaRegisterLogonProcess: %d", ret); __seterrno_from_win_error (LsaNtStatusToWinError (ret)); goto out; } else if (GetLastError () == ERROR_PROC_NOT_FOUND) { debug_printf ("Couldn't load Secur32.dll"); goto out; } /* Get handle to MSV1_0 package. */ str2lsa (name, MSV1_0_PACKAGE_NAME); ret = LsaLookupAuthenticationPackage (lsa_hdl, &name, &package_id); if (ret != STATUS_SUCCESS) { debug_printf ("LsaLookupAuthenticationPackage: %d", ret); __seterrno_from_win_error (LsaNtStatusToWinError (ret)); LsaDeregisterLogonProcess (lsa_hdl); goto out; } /* Create origin. */ str2buf2lsa (origin.str, origin.buf, "Cygwin"); /* Create token source. */ memcpy (ts.SourceName, "Cygwin.1", 8); ts.SourceIdentifier.HighPart = 0; ts.SourceIdentifier.LowPart = 0x0100; /* Get user information. */ extract_nt_dom_user (pw, nt_domain, nt_user); /* Fill subauth with values. */ subbuf.auth.MessageType = MsV1_0NetworkLogon; str2buf2uni (subbuf.auth.LogonDomainName, subbuf.dombuf, nt_domain); str2buf2uni (subbuf.auth.UserName, subbuf.usrbuf, nt_user); str2buf2uni (subbuf.auth.Workstation, subbuf.wkstbuf, ""); memcpy (subbuf.auth.ChallengeToClient, "12345678", MSV1_0_CHALLENGE_LENGTH); str2buf2lsa (subbuf.auth.CaseSensitiveChallengeResponse, subbuf.authinf1, ""); str2buf2lsa (subbuf.auth.CaseInsensitiveChallengeResponse,subbuf.authinf2,""); subbuf.auth.ParameterControl = 0 | (subauth_id << 24); /* Try to logon... */ ret = LsaLogonUser (lsa_hdl, (PLSA_STRING) &origin, Network, package_id, &subbuf, sizeof subbuf, NULL, &ts, (PVOID *) &profile, &size, &luid, &user_token, "a, &ret2); if (ret != STATUS_SUCCESS) { debug_printf ("LsaLogonUser: %d", ret); __seterrno_from_win_error (LsaNtStatusToWinError (ret)); LsaDeregisterLogonProcess (lsa_hdl); goto out; } LsaFreeReturnBuffer (profile); /* Convert to primary token. */ if (!DuplicateTokenEx (user_token, TOKEN_ALL_ACCESS, &sa, SecurityImpersonation, TokenPrimary, &primary_token)) __seterrno ();out: set_process_privilege (SE_TCB_NAME, old_tcb_state); if (user_token != INVALID_HANDLE_VALUE) CloseHandle (user_token); return primary_token;}/* read_sd reads a security descriptor from a file. In case of error, -1 is returned and errno is set. If sd_buf is too small, 0 is returned and sd_size is set to the needed buffer size. On success, 1 is returned. GetFileSecurity() is used instead of BackupRead() to avoid access denied errors if the caller has not the permission to open that file for read. Originally the function should return the size of the SD on success. Unfortunately NT returns 0 in `len' on success, while W2K returns the correct size!*/LONGread_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size){ /* Check parameters */ if (!sd_size) { set_errno (EINVAL); return -1; } debug_printf ("file = %s", file); DWORD len = 0; const char *pfile = file; char fbuf[PATH_MAX]; if (current_codepage == oem_cp) { DWORD fname_len = min (sizeof (fbuf) - 1, strlen (file)); bzero (fbuf, sizeof (fbuf)); OemToCharBuff (file, fbuf, fname_len); pfile = fbuf; } if (!GetFileSecurity (pfile, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, sd_buf, *sd_size, &len)) { __seterrno (); return -1; } debug_printf ("file = %s: len=%d", file, len); if (len > *sd_size) { *sd_size = len; return 0; } return 1;}LONGwrite_sd (const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size){ /* Check parameters */ if (!sd_buf || !sd_size) { set_errno (EINVAL); return -1; } /* No need to be thread save. */ static BOOL first_time = TRUE; if (first_time) { set_process_privilege (SE_RESTORE_NAME); first_time = FALSE; } HANDLE fh; fh = CreateFile (file, WRITE_OWNER | WRITE_DAC, FILE_SHARE_READ | FILE_SHARE_WRITE, &sec_none_nih, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, NULL); if (fh == INVALID_HANDLE_VALUE) { __seterrno (); return -1; } LPVOID context = NULL; DWORD bytes_written = 0; WIN32_STREAM_ID header; memset (&header, 0, sizeof (header)); /* write new security info header */ header.dwStreamId = BACKUP_SECURITY_DATA; header.dwStreamAttributes = STREAM_CONTAINS_SECURITY; header.Size.HighPart = 0; header.Size.LowPart = sd_size; header.dwStreamNameSize = 0; if (!BackupWrite (fh, (LPBYTE) &header, 3 * sizeof (DWORD) + sizeof (LARGE_INTEGER), &bytes_written, FALSE, TRUE, &context)) { __seterrno (); CloseHandle (fh); return -1; } /* write new security descriptor */ if (!BackupWrite (fh, (LPBYTE) sd_buf, header.Size.LowPart + header.dwStreamNameSize, &bytes_written, FALSE, TRUE, &context)) { /* Samba returns ERROR_NOT_SUPPORTED. FAT returns ERROR_INVALID_SECURITY_DESCR. This shouldn't return as error, but better be ignored. */ DWORD ret = GetLastError (); if (ret != ERROR_NOT_SUPPORTED && ret != ERROR_INVALID_SECURITY_DESCR) { __seterrno (); BackupWrite (fh, NULL, 0, &bytes_written, TRUE, TRUE, &context); CloseHandle (fh); return -1; } } /* terminate the restore process */ BackupWrite (fh, NULL, 0, &bytes_written, TRUE, TRUE, &context); CloseHandle (fh); return 0;}static voidget_attribute_from_acl (int * attribute, PACL acl, PSID owner_sid, PSID group_sid, BOOL grp_member){ ACCESS_ALLOWED_ACE *ace; int allow = 0; int deny = 0; int *flags, *anti; for (DWORD i = 0; i < acl->AceCount; ++i) { if (!GetAce (acl, i, (PVOID *) &ace)) continue; if (ace->Header.AceFlags & INHERIT_ONLY) continue; switch (ace->Header.AceType) { case ACCESS_ALLOWED_ACE_TYPE: flags = &allow; anti = &deny; break; case ACCESS_DENIED_ACE_TYPE: flags = &deny; anti = &allow; break; default: continue; } cygsid ace_sid ((PSID) &ace->SidStart); if (ace_sid == well_known_world_sid) { if (ace->Mask & FILE_READ_DATA) *flags |= ((!(*anti & S_IROTH)) ? S_IROTH : 0) | ((!(*anti & S_IRGRP)) ? S_IRGRP : 0) | ((!(*anti & S_IRUSR)) ? S_IRUSR : 0); if (ace->Mask & FILE_WRITE_DATA) *flags |= ((!(*anti & S_IWOTH)) ? S_IWOTH : 0) | ((!(*anti & S_IWGRP)) ? S_IWGRP : 0) | ((!(*anti & S_IWUSR)) ? S_IWUSR : 0); if (ace->Mask & FILE_EXECUTE) *flags |= ((!(*anti & S_IXOTH)) ? S_IXOTH : 0) | ((!(*anti & S_IXGRP)) ? S_IXGRP : 0) | ((!(*anti & S_IXUSR)) ? S_IXUSR : 0); if ((*attribute & S_IFDIR) && (ace->Mask & (FILE_WRITE_DATA | FILE_EXECUTE | FILE_DELETE_CHILD)) == (FILE_WRITE_DATA | FILE_EXECUTE)) *flags |= S_ISVTX; } else if (ace_sid == well_known_null_sid) { /* Read SUID, SGID and VTX bits from NULL ACE. */ if (ace->Mask & FILE_READ_DATA) *flags |= S_ISVTX; if (ace->Mask & FILE_WRITE_DATA) *flags |= S_ISGID; if (ace->Mask & FILE_APPEND_DATA) *flags |= S_ISUID; } else if (ace_sid == owner_sid) { if (ace->Mask & FILE_READ_DATA) *flags |= ((!(*anti & S_IRUSR)) ? S_IRUSR : 0); if (ace->Mask & FILE_WRITE_DATA) *flags |= ((!(*anti & S_IWUSR)) ? S_IWUSR : 0); if (ace->Mask & FILE_EXECUTE) *flags |= ((!(*anti & S_IXUSR)) ? S_IXUSR : 0); } else if (ace_sid == group_sid) { if (ace->Mask & FILE_READ_DATA) *flags |= ((!(*anti & S_IRGRP)) ? S_IRGRP : 0) | ((grp_member && !(*anti & S_IRUSR)) ? S_IRUSR : 0); if (ace->Mask & FILE_WRITE_DATA) *flags |= ((!(*anti & S_IWGRP)) ? S_IWGRP : 0) | ((grp_member && !(*anti & S_IWUSR)) ? S_IWUSR : 0); if (ace->Mask & FILE_EXECUTE) *flags |= ((!(*anti & S_IXGRP)) ? S_IXGRP : 0) | ((grp_member && !(*anti & S_IXUSR)) ? S_IXUSR : 0); } } *attribute &= ~(S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX | S_ISGID | S_ISUID); if (owner_sid && group_sid && EqualSid (owner_sid, group_sid) /* FIXME: temporary exception for /var/empty */ && well_known_system_sid != group_sid) { allow &= ~(S_IRGRP | S_IWGRP | S_IXGRP); allow |= (((allow & S_IRUSR) ? S_IRGRP : 0) | ((allow & S_IWUSR) ? S_IWGRP : 0) | ((allow & S_IXUSR) ? S_IXGRP : 0)); } *attribute |= allow; return;}static intget_nt_attribute (const char *file, int *attribute, __uid32_t *uidret, __gid32_t *gidret){ if (!wincap.has_security ()) return 0; syscall_printf ("file: %s", file); /* Yeah, sounds too much, but I've seen SDs of 2100 bytes! */ DWORD sd_size = 4096; char sd_buf[4096]; PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf; int ret; if ((ret = read_sd (file, psd, &sd_size)) <= 0) { debug_printf ("read_sd %E"); return ret; } PSID owner_sid; PSID group_sid; BOOL dummy; if (!GetSecurityDescriptorOwner (psd, &owner_sid, &dummy)) debug_printf ("GetSecurityDescriptorOwner %E"); if (!GetSecurityDescriptorGroup (psd, &group_sid, &dummy)) debug_printf ("GetSecurityDescriptorGroup %E"); PACL acl; BOOL acl_exists; if (!GetSecurityDescriptorDacl (psd, &acl_exists, &acl, &dummy)) { __seterrno (); debug_printf ("GetSecurityDescriptorDacl %E"); return -1; } __uid32_t uid = cygsid (owner_sid).get_uid (); __gid32_t gid = cygsid (group_sid).get_gid (); if (uidret) *uidret = uid; if (gidret) *gidret = gid; if (!attribute) { syscall_printf ("file: %s uid %d, gid %d", file, uid, gid); return 0; } BOOL grp_member = is_grp_member (uid, gid); if (!acl_exists || !acl) { *attribute |= S_IRWXU | S_IRWXG | S_IRWXO; syscall_printf ("file: %s No ACL = %x, uid %d, gid %d", file, *attribute, uid, gid); return 0; } get_attribute_from_acl (attribute, acl, owner_sid, group_sid, grp_member); syscall_printf ("file: %s %x, uid %d, gid %d", file, *attribute, uid, gid); return 0;}intget_file_attribute (int use_ntsec, const char *file, int *attribute, __uid32_t *uidret, __gid32_t *gidret){ int res; if (use_ntsec && allow_ntsec) { res = get_nt_attribute (file, attribute, uidret, gidret); if (attribute && (*attribute & S_IFLNK) == S_IFLNK) *attribute |= S_IRWXU | S_IRWXG | S_IRWXO; return res; } if (uidret) *uidret = getuid32 (); if (gidret) *gidret = getgid32 (); if (!attribute) return 0; if (allow_ntea) { int oatt = *attribute; res = NTReadEA (file, ".UNIXATTR", (char *)attribute, sizeof (*attribute)); *attribute |= oatt; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -