@@ -5541,146 +5541,6 @@ os__path_normpath_impl(PyObject *module, PyObject *path) |
5541 | 5541 | return result; |
5542 | 5542 | } |
5543 | 5543 |
|
5544 | | -#ifdef MS_WINDOWS |
5545 | | - |
5546 | | -/* We centralise SECURITY_ATTRIBUTE initialization based around |
5547 | | -templates that will probably mostly match common POSIX mode settings. |
5548 | | -The _Py_SECURITY_ATTRIBUTE_DATA structure contains temporary data, as |
5549 | | -a constructed SECURITY_ATTRIBUTE structure typically refers to memory |
5550 | | -that has to be alive while it's being used. |
5551 | | -
|
5552 | | -Typical use will look like: |
5553 | | - SECURITY_ATTRIBUTES *pSecAttr = NULL; |
5554 | | - struct _Py_SECURITY_ATTRIBUTE_DATA secAttrData; |
5555 | | - int error, error2; |
5556 | | -
|
5557 | | - Py_BEGIN_ALLOW_THREADS |
5558 | | - switch (mode) { |
5559 | | - case 0x1C0: // 0o700 |
5560 | | - error = initializeMkdir700SecurityAttributes(&pSecAttr, &secAttrData); |
5561 | | - break; |
5562 | | - ... |
5563 | | - default: |
5564 | | - error = initializeDefaultSecurityAttributes(&pSecAttr, &secAttrData); |
5565 | | - break; |
5566 | | - } |
5567 | | -
|
5568 | | - if (!error) { |
5569 | | - // do operation, passing pSecAttr |
5570 | | - } |
5571 | | -
|
5572 | | - // Unconditionally clear secAttrData. |
5573 | | - error2 = clearSecurityAttributes(&pSecAttr, &secAttrData); |
5574 | | - if (!error) { |
5575 | | - error = error2; |
5576 | | - } |
5577 | | - Py_END_ALLOW_THREADS |
5578 | | -
|
5579 | | - if (error) { |
5580 | | - PyErr_SetFromWindowsErr(error); |
5581 | | - return NULL; |
5582 | | - } |
5583 | | -*/ |
5584 | | - |
5585 | | -struct _Py_SECURITY_ATTRIBUTE_DATA { |
5586 | | - SECURITY_ATTRIBUTES securityAttributes; |
5587 | | - PACL acl; |
5588 | | - SECURITY_DESCRIPTOR sd; |
5589 | | - EXPLICIT_ACCESS_W ea[4]; |
5590 | | - char sid[64]; |
5591 | | -}; |
5592 | | - |
5593 | | -static int |
5594 | | -initializeDefaultSecurityAttributes( |
5595 | | - PSECURITY_ATTRIBUTES *securityAttributes, |
5596 | | - struct _Py_SECURITY_ATTRIBUTE_DATA *data |
5597 | | -) { |
5598 | | - assert(securityAttributes); |
5599 | | - assert(data); |
5600 | | - *securityAttributes = NULL; |
5601 | | - memset(data, 0, sizeof(*data)); |
5602 | | - return 0; |
5603 | | -} |
5604 | | - |
5605 | | -static int |
5606 | | -initializeMkdir700SecurityAttributes( |
5607 | | - PSECURITY_ATTRIBUTES *securityAttributes, |
5608 | | - struct _Py_SECURITY_ATTRIBUTE_DATA *data |
5609 | | -) { |
5610 | | - assert(securityAttributes); |
5611 | | - assert(data); |
5612 | | - *securityAttributes = NULL; |
5613 | | - memset(data, 0, sizeof(*data)); |
5614 | | - |
5615 | | - if (!InitializeSecurityDescriptor(&data->sd, SECURITY_DESCRIPTOR_REVISION) |
5616 | | - || !SetSecurityDescriptorGroup(&data->sd, NULL, TRUE)) { |
5617 | | - return GetLastError(); |
5618 | | - } |
5619 | | - |
5620 | | - int use_alias = 0; |
5621 | | - DWORD cbSid = sizeof(data->sid); |
5622 | | - if (!CreateWellKnownSid(WinCreatorOwnerRightsSid, NULL, (PSID)data->sid, &cbSid)) { |
5623 | | - use_alias = 1; |
5624 | | - } |
5625 | | - |
5626 | | - data->securityAttributes.nLength = sizeof(SECURITY_ATTRIBUTES); |
5627 | | - data->ea[0].grfAccessPermissions = GENERIC_ALL; |
5628 | | - data->ea[0].grfAccessMode = SET_ACCESS; |
5629 | | - data->ea[0].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; |
5630 | | - if (use_alias) { |
5631 | | - data->ea[0].Trustee.TrusteeForm = TRUSTEE_IS_NAME; |
5632 | | - data->ea[0].Trustee.TrusteeType = TRUSTEE_IS_ALIAS; |
5633 | | - data->ea[0].Trustee.ptstrName = L"CURRENT_USER"; |
5634 | | - } else { |
5635 | | - data->ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; |
5636 | | - data->ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; |
5637 | | - data->ea[0].Trustee.ptstrName = (LPWCH)(SID*)data->sid; |
5638 | | - } |
5639 | | - |
5640 | | - data->ea[1].grfAccessPermissions = GENERIC_ALL; |
5641 | | - data->ea[1].grfAccessMode = SET_ACCESS; |
5642 | | - data->ea[1].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; |
5643 | | - data->ea[1].Trustee.TrusteeForm = TRUSTEE_IS_NAME; |
5644 | | - data->ea[1].Trustee.TrusteeType = TRUSTEE_IS_ALIAS; |
5645 | | - data->ea[1].Trustee.ptstrName = L"SYSTEM"; |
5646 | | - |
5647 | | - data->ea[2].grfAccessPermissions = GENERIC_ALL; |
5648 | | - data->ea[2].grfAccessMode = SET_ACCESS; |
5649 | | - data->ea[2].grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT; |
5650 | | - data->ea[2].Trustee.TrusteeForm = TRUSTEE_IS_NAME; |
5651 | | - data->ea[2].Trustee.TrusteeType = TRUSTEE_IS_ALIAS; |
5652 | | - data->ea[2].Trustee.ptstrName = L"ADMINISTRATORS"; |
5653 | | - |
5654 | | - int r = SetEntriesInAclW(3, data->ea, NULL, &data->acl); |
5655 | | - if (r) { |
5656 | | - return r; |
5657 | | - } |
5658 | | - if (!SetSecurityDescriptorDacl(&data->sd, TRUE, data->acl, FALSE)) { |
5659 | | - return GetLastError(); |
5660 | | - } |
5661 | | - data->securityAttributes.lpSecurityDescriptor = &data->sd; |
5662 | | - *securityAttributes = &data->securityAttributes; |
5663 | | - return 0; |
5664 | | -} |
5665 | | - |
5666 | | -static int |
5667 | | -clearSecurityAttributes( |
5668 | | - PSECURITY_ATTRIBUTES *securityAttributes, |
5669 | | - struct _Py_SECURITY_ATTRIBUTE_DATA *data |
5670 | | -) { |
5671 | | - assert(securityAttributes); |
5672 | | - assert(data); |
5673 | | - *securityAttributes = NULL; |
5674 | | - if (data->acl) { |
5675 | | - if (LocalFree((void *)data->acl)) { |
5676 | | - return GetLastError(); |
5677 | | - } |
5678 | | - } |
5679 | | - return 0; |
5680 | | -} |
5681 | | - |
5682 | | -#endif |
5683 | | - |
5684 | 5544 | /*[clinic input] |
5685 | 5545 | os.mkdir |
5686 | 5546 |
|
@@ -5713,8 +5573,8 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) |
5713 | 5573 | #ifdef MS_WINDOWS |
5714 | 5574 | int error = 0; |
5715 | 5575 | int pathError = 0; |
| 5576 | + SECURITY_ATTRIBUTES secAttr = { sizeof(secAttr) }; |
5716 | 5577 | SECURITY_ATTRIBUTES *pSecAttr = NULL; |
5717 | | - struct _Py_SECURITY_ATTRIBUTE_DATA secAttrData; |
5718 | 5578 | #endif |
5719 | 5579 | #ifdef HAVE_MKDIRAT |
5720 | 5580 | int mkdirat_unavailable = 0; |
@@ -5727,26 +5587,34 @@ os_mkdir_impl(PyObject *module, path_t *path, int mode, int dir_fd) |
5727 | 5587 |
|
5728 | 5588 | #ifdef MS_WINDOWS |
5729 | 5589 | Py_BEGIN_ALLOW_THREADS |
5730 | | - switch (mode) { |
5731 | | - case 0x1C0: // 0o700 |
5732 | | - error = initializeMkdir700SecurityAttributes(&pSecAttr, &secAttrData); |
5733 | | - break; |
5734 | | - default: |
5735 | | - error = initializeDefaultSecurityAttributes(&pSecAttr, &secAttrData); |
5736 | | - break; |
| 5590 | + if (mode == 0700 /* 0o700 */) { |
| 5591 | + ULONG sdSize; |
| 5592 | + pSecAttr = &secAttr; |
| 5593 | + // Set a discreationary ACL (D) that is protected (P) and includes |
| 5594 | + // inheritable (OICI) entries that allow (A) full control (FA) to |
| 5595 | + // SYSTEM (SY), Administrators (BA), and the owner (OW). |
| 5596 | + if (!ConvertStringSecurityDescriptorToSecurityDescriptorW( |
| 5597 | + L"D:P(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)(A;OICI;FA;;;OW)", |
| 5598 | + SDDL_REVISION_1, |
| 5599 | + &secAttr.lpSecurityDescriptor, |
| 5600 | + &sdSize |
| 5601 | + )) { |
| 5602 | + error = GetLastError(); |
| 5603 | + } |
5737 | 5604 | } |
5738 | 5605 | if (!error) { |
5739 | 5606 | result = CreateDirectoryW(path->wide, pSecAttr); |
5740 | | - error = clearSecurityAttributes(&pSecAttr, &secAttrData); |
5741 | | - } else { |
5742 | | - // Ignore error from "clear" - we have a more interesting one already |
5743 | | - clearSecurityAttributes(&pSecAttr, &secAttrData); |
| 5607 | + if (secAttr.lpSecurityDescriptor && |
| 5608 | + // uncommonly, LocalFree returns non-zero on error, but still uses |
| 5609 | + // GetLastError() to see what the error code is |
| 5610 | + LocalFree(secAttr.lpSecurityDescriptor)) { |
| 5611 | + error = GetLastError(); |
| 5612 | + } |
5744 | 5613 | } |
5745 | 5614 | Py_END_ALLOW_THREADS |
5746 | 5615 |
|
5747 | 5616 | if (error) { |
5748 | | - PyErr_SetFromWindowsErr(error); |
5749 | | - return NULL; |
| 5617 | + return PyErr_SetFromWindowsErr(error); |
5750 | 5618 | } |
5751 | 5619 | if (!result) { |
5752 | 5620 | return path_error(path); |
|