mhammond / pywin32

Python for Windows (pywin32) Extensions
5.04k stars 796 forks source link

Given the KB5004442—Manage changes for Windows DCOM Server Security Feature Bypass (CVE-2021-26414) a two node OPC-DA connection on my network stop working , I altered the register as Microsoft recomended, but as described on KB it will not be possible after march 2023. Are you aware of this DCOM issue? Do you intend to resolve this issue in pywin32? #1958

Open ClaudioCamera opened 2 years ago

ClaudioCamera commented 2 years ago

Note that issues in this repository are only for bugs or feature requests in the pywin32.

If you need support or help using this package, please follow these instructions - support or help requests will be closed without comment.

For all bugs, please provide the following information.

ClaudioCamera commented 2 years ago

It Follows the error I have gotten : Traceback (most recent call last): File "D:\Programs\Python37-32\lib\site-packages\OpenOPC.py", line 223, in connect self._opc.Connect(s, opc_host) File "C:\Users\ASETA7\AppData\Local\Temp\2\gen_py\3.7\F8582D24-88FB-11D0-B850-00C0F0104305x0x1x0.py", line 208, in Connect , Node) pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, None, None, None, 0, -2147467259), None)

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "C:\Users\ASETA7\Documents\teste.py", line 10, in opc.connect(opc_server,opc_host) File "D:\Programs\Python37-32\lib\site-packages\OpenOPC.py", line 227, in connect raise OPCError(error_msg) OpenOPC.OPCError: Connect: -2147467259

mhammond commented 1 year ago

I'm not aware of the issue and a quick look failed to inform me what action pywin32 could take. There's nothing in the above code snippet to help me understand - non-pywin32 code is throwing an exception. What changes need to be made to pywin32?

davibelo commented 1 year ago

@mhammond . This issue is related with minimal authentication level for DCOM requests that changed to packet integrity..

KB5004442 says: "This update will automatically raise authentication level for all non-anonymous activation requests from DCOM clients to RPC_C_AUTHN_LEVEL_PKT_INTEGRITY"

Unfortunately, I tried but I didn't find exactly where in pywin32 is the choosen authentication level for DCOM.

If you could help us, will be awesome. Thank you very much.

mhammond commented 1 year ago

I don't think pywin2 chooses an authentication level. pywin32 offers thin wrappers around COM, so it will be up to the consumers to choose the authentication level. Do you have any examples of changes other non-pywin32 dcom consumers are making?

davibelo commented 1 year ago

@mhammond . humm. I understand. So I look better on pywin32 and found this:

https://github.com/mhammond/pywin32/blob/main/com/win32com/src/PythonCOM.cpp

static PyObject *pythoncom_CoInitializeSecurity(PyObject *self, PyObject *args)
{
    CHECK_PFN(CoInitializeSecurity);
    DWORD cAuthSvc;
    SOLE_AUTHENTICATION_SERVICE *pAS = NULL;
    DWORD dwAuthnLevel;
    DWORD dwImpLevel;
    DWORD dwCapabilities;
    PSECURITY_DESCRIPTOR pSD = NULL, pSD_absolute = NULL;
    IID appid;
    IAccessControl *pIAC = NULL;
    PyObject *obSD, *obAuthSvc, *obReserved1, *obReserved2, *obAuthInfo;
    if (!PyArg_ParseTuple(
            args, "OOOiiOiO:CoInitializeSecurity",
            &obSD,  // @pyparm <o PySECURITY_DESCRIPTOR>|sd||Security descriptor containing access permissions for
                    // process' objects, can be None. <nl>If Capabilities contains EOAC_APPID, sd should be an AppId
                    // (guid), or None to use server executable. <nl>If Capabilities contains EOAC_ACCESS_CONTROL, sd
                    // parameter should be an IAccessControl interface.
            &obAuthSvc,  // @pyparm object|authSvc||A value of None tells COM to choose which authentication services to
                         // use.  An empty list means use no services.
            &obReserved1,   // @pyparm object|reserved1||Must be None
            &dwAuthnLevel,  // @pyparm int|authnLevel||One of pythoncom.**RPC_C_AUTHN_LEVEL_* values**. The default
                            // authentication level for proxies. On the server side, COM will fail calls that arrive at
                            // a lower level. All calls to AddRef and Release are made at this level.

Considering what KB5004442 says: "This update will automatically raise authentication level for all non-anonymous activation requests from DCOM clients to RPC_C_AUTHN_LEVEL_PKT_INTEGRITY"

Below is a small part of the code where I use pywin32 for DCOM: https://github.com/mkwiatkowski/openopc/blob/master/src/OpenOPC.py

class client():
   def __init__(self, opc_class=None, client_name=None):
      """Instantiate OPC automation class"""

      self.callback_queue = Queue()

      pythoncom.CoInitialize()

@ClaudioCamera

I think that the case here is only use that method pythoncom.CoInitializeSecurity() with the argument dwAuthnLevel set on RPC_C_AUTHN_LEVEL_PKT_INTEGRITY.

@mhammond the use could be this?

pythoncom.CoInitializeSecurity(dwAuthnLevel=RPC_C_AUTHN_LEVEL_PKT_INTEGRITY)

(I know this question is better suited for email list, but we are already here, so...)

mhammond commented 1 year ago

@mhammond the use could be this?

Sorry, but I have no idea :(

davibelo commented 1 year ago

@ClaudioCamera @mhammond . I tested and it was successful.

It´s is necessary to use the CoinitializaSecurity method

pythoncom.CoInitializeSecurity( None, None, None, pythoncom.RPC_C_AUTHN_LEVEL_PKT_INTEGRITY, pythoncom.RPC_C_IMP_LEVEL_IMPERSONATE, None, pythoncom.EOAC_NONE, None )

duduyoyo commented 3 months ago

If you call CoInitializeSecurity() explicitly, you need set authentication level to RPC_C_AUTHN_LEVEL_PKT_INTEGRITY as shown above. If it isn't called, you can leave it alone and MS will change authentication level to RPC_C_AUTHN_LEVEL_PKT_INTEGRITY underneath. This can be verified if you hook up Wireshark doing packet analysis.

@ClaudioCamera There is another solution to access OPC DA in Python without worrying about DCOM, check here