📄 security.cc
字号:
/* security.cc: NT security functions Copyright 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de Completely rewritten by Corinna Vinschen <corinna@vinschen.de>This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license. Please consult the file "CYGWIN_LICENSE" fordetails. */#include "winsup.h"#include <grp.h>#include <pwd.h>#include <unistd.h>#include <stdlib.h>#include <errno.h>#include <limits.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/acl.h>#include <ctype.h>#include <winnls.h>#include <wingdi.h>#include <winuser.h>#include <wininet.h>#include <ntsecapi.h>#include <subauth.h>#include <aclapi.h>#include "cygerrno.h"#include "security.h"#include "fhandler.h"#include "path.h"#include "dtable.h"#include "pinfo.h"#include "cygheap.h"#include <ntdef.h>#include "ntdll.h"#include "lm.h"extern BOOL allow_ntea;BOOL allow_ntsec;/* allow_smbntsec is handled exclusively in path.cc (path_conv::check). It's defined here because of it's strong relationship to allow_ntsec. The default is TRUE to reflect the old behaviour. */BOOL allow_smbntsec;cygsid *cygsidlist::alloc_sids (int n){ if (n > 0) return (cygsid *) cmalloc (HEAP_STR, n * sizeof (cygsid)); else return NULL;}voidcygsidlist::free_sids (){ if (sids) cfree (sids); sids = NULL; count = maxcount = 0; type = cygsidlist_empty;}extern "C" voidcygwin_set_impersonation_token (const HANDLE hToken){ debug_printf ("set_impersonation_token (%d)", hToken); if (cygheap->user.token != hToken) { cygheap->user.token = hToken; cygheap->user.impersonated = FALSE; }}voidextract_nt_dom_user (const struct passwd *pw, char *domain, char *user){ char *d, *u, *c; domain[0] = 0; strlcpy (user, pw->pw_name, UNLEN + 1); debug_printf ("pw_gecos = %x (%s)", pw->pw_gecos, pw->pw_gecos); if ((d = strstr (pw->pw_gecos, "U-")) != NULL && (d == pw->pw_gecos || d[-1] == ',')) { c = strchr (d + 2, ','); if ((u = strchr (d + 2, '\\')) == NULL || (c != NULL && u > c)) u = d + 1; else if (u - d <= INTERNET_MAX_HOST_NAME_LENGTH + 2) strlcpy (domain, d + 2, u - d - 1); if (c == NULL) c = u + UNLEN + 1; if (c - u <= UNLEN + 1) strlcpy (user, u + 1, c - u); } if (domain[0]) return; cygsid psid; DWORD ulen = UNLEN + 1; DWORD dlen = INTERNET_MAX_HOST_NAME_LENGTH + 1; SID_NAME_USE use; if (psid.getfrompw (pw)) LookupAccountSid (NULL, psid, user, &ulen, domain, &dlen, &use);}extern "C" HANDLEcygwin_logon_user (const struct passwd *pw, const char *password){ if (!wincap.has_security ()) { set_errno (ENOSYS); return INVALID_HANDLE_VALUE; } if (!pw) { set_errno (EINVAL); return INVALID_HANDLE_VALUE; } char nt_domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; char nt_user[UNLEN + 1]; HANDLE hToken; extract_nt_dom_user (pw, nt_domain, nt_user); debug_printf ("LogonUserA (%s, %s, %s, ...)", nt_user, nt_domain, password); if (!LogonUserA (nt_user, *nt_domain ? nt_domain : NULL, (char *) password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &hToken) || !SetHandleInformation (hToken, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) { __seterrno (); return INVALID_HANDLE_VALUE; } debug_printf ("%d = logon_user(%s,...)", hToken, pw->pw_name); return hToken;}static voidstr2lsa (LSA_STRING &tgt, const char *srcstr){ tgt.Length = strlen (srcstr); tgt.MaximumLength = tgt.Length + 1; tgt.Buffer = (PCHAR) srcstr;}static voidstr2buf2lsa (LSA_STRING &tgt, char *buf, const char *srcstr){ tgt.Length = strlen (srcstr); tgt.MaximumLength = tgt.Length + 1; tgt.Buffer = (PCHAR) buf; memcpy (buf, srcstr, tgt.MaximumLength);}voidstr2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr){ tgt.Length = strlen (srcstr) * sizeof (WCHAR); tgt.MaximumLength = tgt.Length + sizeof (WCHAR); tgt.Buffer = (PWCHAR) buf; sys_mbstowcs (buf, srcstr, tgt.MaximumLength);}#if 0 /* unused */static voidlsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size){ size = (size - 1) * sizeof (WCHAR); if (src.Length < size) size = src.Length; memcpy (tgt, src.Buffer, size); size >>= 1; tgt[size] = 0;}#endifstatic voidlsa2str (char *tgt, LSA_UNICODE_STRING &src, int size){ if (src.Length / 2 < size) size = src.Length / 2; sys_wcstombs (tgt, src.Buffer, size); tgt[size] = 0;}static LSA_HANDLEopen_local_policy (){ LSA_OBJECT_ATTRIBUTES oa = { 0, 0, 0, 0, 0, 0 }; LSA_HANDLE lsa = INVALID_HANDLE_VALUE; NTSTATUS ret = LsaOpenPolicy (NULL, &oa, POLICY_EXECUTE, &lsa); if (ret != STATUS_SUCCESS) __seterrno_from_win_error (LsaNtStatusToWinError (ret)); return lsa;}static voidclose_local_policy (LSA_HANDLE &lsa){ if (lsa != INVALID_HANDLE_VALUE) LsaClose (lsa); lsa = INVALID_HANDLE_VALUE;}#if 0 /* unused */static BOOLget_lsa_srv_inf (LSA_HANDLE lsa, char *logonserver, char *domain){ NET_API_STATUS ret; WCHAR *buf; char name[INTERNET_MAX_HOST_NAME_LENGTH + 1]; WCHAR account[INTERNET_MAX_HOST_NAME_LENGTH + 1]; WCHAR primary[INTERNET_MAX_HOST_NAME_LENGTH + 1]; PPOLICY_ACCOUNT_DOMAIN_INFO adi; PPOLICY_PRIMARY_DOMAIN_INFO pdi; if ((ret = LsaQueryInformationPolicy (lsa, PolicyAccountDomainInformation, (PVOID *) &adi)) != STATUS_SUCCESS) { __seterrno_from_win_error (LsaNtStatusToWinError (ret)); return FALSE; } lsa2wchar (account, adi->DomainName, INTERNET_MAX_HOST_NAME_LENGTH + 1); LsaFreeMemory (adi); if ((ret = LsaQueryInformationPolicy (lsa, PolicyPrimaryDomainInformation, (PVOID *) &pdi)) != STATUS_SUCCESS) { __seterrno_from_win_error (LsaNtStatusToWinError (ret)); return FALSE; } lsa2wchar (primary, pdi->Name, INTERNET_MAX_HOST_NAME_LENGTH + 1); LsaFreeMemory (pdi); /* If the SID given in the primary domain info is NULL, the machine is not member of a domain. The name in the primary domain info is the name of the workgroup then. */ if (pdi->Sid && (ret = NetGetDCName (NULL, primary, (LPBYTE *) &buf)) == STATUS_SUCCESS) { sys_wcstombs (name, buf, INTERNET_MAX_HOST_NAME_LENGTH + 1); strcpy (logonserver, name); if (domain) sys_wcstombs (domain, primary, INTERNET_MAX_HOST_NAME_LENGTH + 1); } else { sys_wcstombs (name, account, INTERNET_MAX_HOST_NAME_LENGTH + 1); strcpy (logonserver, "\\\\"); strcat (logonserver, name); if (domain) sys_wcstombs (domain, account, INTERNET_MAX_HOST_NAME_LENGTH + 1); } if (ret == STATUS_SUCCESS) NetApiBufferFree (buf); return TRUE;}#endifBOOLget_logon_server (const char *domain, char *server, WCHAR *wserver){ WCHAR wdomain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; NET_API_STATUS ret; WCHAR *buf; DWORD size = INTERNET_MAX_HOST_NAME_LENGTH + 1; /* Empty domain is interpreted as local system */ if ((GetComputerName (server + 2, &size)) && (strcasematch (domain, server + 2) || !domain[0])) { server[0] = server[1] = '\\'; if (wserver) sys_mbstowcs (wserver, server, INTERNET_MAX_HOST_NAME_LENGTH + 1); return TRUE; } /* Try to get the primary domain controller for the domain */ sys_mbstowcs (wdomain, domain, INTERNET_MAX_HOST_NAME_LENGTH + 1); if ((ret = NetGetDCName (NULL, wdomain, (LPBYTE *) &buf)) == STATUS_SUCCESS) { sys_wcstombs (server, buf, INTERNET_MAX_HOST_NAME_LENGTH + 1); if (wserver) for (WCHAR *ptr1 = buf; (*wserver++ = *ptr1++);) ; NetApiBufferFree (buf); return TRUE; } __seterrno_from_win_error (ret); return FALSE;}static BOOLget_user_groups (WCHAR *wlogonserver, cygsidlist &grp_list, char *user, char *domain){ char dgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; WCHAR wuser[UNLEN + 1]; sys_mbstowcs (wuser, user, UNLEN + 1); LPGROUP_USERS_INFO_0 buf; DWORD cnt, tot, len; NET_API_STATUS ret; /* Look only on logonserver */ ret = NetUserGetGroups (wlogonserver, wuser, 0, (LPBYTE *) &buf, MAX_PREFERRED_LENGTH, &cnt, &tot); if (ret) { __seterrno_from_win_error (ret); /* It's no error when the user name can't be found. */ return ret == NERR_UserNotFound; } len = strlen (domain); strcpy (dgroup, domain); dgroup[len++] = '\\'; for (DWORD i = 0; i < cnt; ++i) { cygsid gsid; DWORD glen = sizeof (gsid); char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; DWORD dlen = sizeof (domain); SID_NAME_USE use = SidTypeInvalid; sys_wcstombs (dgroup + len, buf[i].grui0_name, GNLEN + 1); if (!LookupAccountName (NULL, dgroup, gsid, &glen, domain, &dlen, &use)) debug_printf ("LookupAccountName(%s): %E", dgroup); else if (legal_sid_type (use)) grp_list += gsid; else debug_printf ("Global group %s invalid. Domain: %s Use: %d", dgroup, domain, use); } NetApiBufferFree (buf); return TRUE;}static BOOLis_group_member (WCHAR *wgroup, PSID pusersid, cygsidlist &grp_list){ LPLOCALGROUP_MEMBERS_INFO_0 buf; DWORD cnt, tot; NET_API_STATUS ret; BOOL retval = FALSE; /* Members can be users or global groups */ ret = NetLocalGroupGetMembers (NULL, wgroup, 0, (LPBYTE *) &buf, MAX_PREFERRED_LENGTH, &cnt, &tot, NULL); if (ret) return FALSE; for (DWORD bidx = 0; !retval && bidx < cnt; ++bidx) if (EqualSid (pusersid, buf[bidx].lgrmi0_sid)) retval = TRUE; else for (int glidx = 0; !retval && glidx < grp_list.count; ++glidx) if (EqualSid (grp_list.sids[glidx], buf[bidx].lgrmi0_sid)) retval = TRUE; NetApiBufferFree (buf); return retval;}static BOOLget_user_local_groups (cygsidlist &grp_list, PSID pusersid){ LPLOCALGROUP_INFO_0 buf; DWORD cnt, tot; NET_API_STATUS ret; ret = NetLocalGroupEnum (NULL, 0, (LPBYTE *) &buf, MAX_PREFERRED_LENGTH, &cnt, &tot, NULL); if (ret) { __seterrno_from_win_error (ret); return FALSE; } char bgroup[sizeof ("BUILTIN\\") + GNLEN] = "BUILTIN\\"; char lgroup[INTERNET_MAX_HOST_NAME_LENGTH + GNLEN + 2]; const DWORD blen = sizeof ("BUILTIN\\") - 1; DWORD llen = INTERNET_MAX_HOST_NAME_LENGTH + 1; if (!GetComputerNameA (lgroup, &llen)) { __seterrno (); return FALSE; } lgroup[llen++] = '\\'; for (DWORD i = 0; i < cnt; ++i) if (is_group_member (buf[i].lgrpi0_name, pusersid, grp_list)) { cygsid gsid; DWORD glen = sizeof (gsid); char domain[INTERNET_MAX_HOST_NAME_LENGTH + 1]; DWORD dlen = sizeof (domain); SID_NAME_USE use = SidTypeInvalid; sys_wcstombs (bgroup + blen, buf[i].lgrpi0_name, GNLEN + 1); if (!LookupAccountName (NULL, bgroup, gsid, &glen, domain, &dlen, &use)) { if (GetLastError () != ERROR_NONE_MAPPED) debug_printf ("LookupAccountName(%s): %E", bgroup); strcpy (lgroup + llen, bgroup + blen); if (!LookupAccountName (NULL, lgroup, gsid, &glen, domain, &dlen, &use)) debug_printf ("LookupAccountName(%s): %E", lgroup); } if (!legal_sid_type (use)) debug_printf ("Rejecting local %s. use: %d", bgroup + blen, use); else if (!grp_list.contains (gsid)) grp_list += gsid; } NetApiBufferFree (buf); return TRUE;}static BOOLsid_in_token_groups (PTOKEN_GROUPS grps, cygsid &sid){ if (!grps) return FALSE; for (DWORD i = 0; i < grps->GroupCount; ++i) if (sid == grps->Groups[i].Sid) return TRUE; return FALSE;}#if 0 /* Unused */static BOOLget_user_primary_group (WCHAR *wlogonserver, const char *user, PSID pusersid, cygsid &pgrpsid){ LPUSER_INFO_3 buf; WCHAR wuser[UNLEN + 1]; NET_API_STATUS ret; BOOL retval = FALSE; UCHAR count = 0; if (well_known_system_sid == pusersid) { pgrpsid = well_known_system_sid; return TRUE; } sys_mbstowcs (wuser, user, UNLEN + 1); ret = NetUserGetInfo (wlogonserver, wuser, 3, (LPBYTE *) &buf); if (ret) { __seterrno_from_win_error (ret); return FALSE; } pgrpsid = pusersid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -