Derby
  1. Derby
  2. DERBY-962

Upgrade default security mechanism in client to use encrypted userid password if client can support it.

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 10.2.1.6
    • Component/s: Network Client
    • Labels:
      None

      Description

      Currently in the client, if userid and password are set in the connection url, the default security mechanism is upgraded to USRIDPWD (which is clear text userid and password). This seems to be a security hole here.

      Current client driver supports encrypted userid/password (EUSRIDPWD) via the use of DH key-agreement protocol - however current Open Group DRDA specifications imposes small prime and base generator values (256 bits) that prevents other JCE's (apt from ibm jce) to be used as java cryptography providers.

      Some thoughts:
      – client can make a check to see if it the jvm it is running in supports the encryption necessary for EUSRIDPWD. If it supports, then the client can upgrade to EUSRIDPWD.
      – if the jvm the client is running is , doesnt support encryption requirements for EUSRIDPWD, then the security mechanism will be set to USRIDPWD.

      DERBY-528 will add support for strong userid and password which is another option to send encrypted passwords across the wire. When this gets added, maybe this can be considered as one of the upgrade options after EUSRIDPWD.

      1. d962_javadoc.2.diff.txt
        1 kB
        Sunitha Kambhampati
      2. d962_javadoc.diff.txt
        1 kB
        Sunitha Kambhampati
      3. Derby962.diff.txt
        140 kB
        Sunitha Kambhampati
      4. Derby962.stat.txt
        0.8 kB
        Sunitha Kambhampati
      5. Derby962_forreview.diff.txt
        137 kB
        Sunitha Kambhampati
      6. Derby962_forreview.stat.txt
        0.8 kB
        Sunitha Kambhampati
      7. 962_table.txt
        5 kB
        Sunitha Kambhampati

        Issue Links

          Activity

          Hide
          Andrew McIntyre added a comment -

          This issue has been resolved for over a year with no further movement. Closing.

          Show
          Andrew McIntyre added a comment - This issue has been resolved for over a year with no further movement. Closing.
          Hide
          Sunitha Kambhampati added a comment -

          Thanks Kathey. Please look at this patch (d962_javadoc.2.diff.txt)

          I ran javadoc and did clobber and ant all ok. Thanks.

          Show
          Sunitha Kambhampati added a comment - Thanks Kathey. Please look at this patch (d962_javadoc.2.diff.txt) I ran javadoc and did clobber and ant all ok. Thanks.
          Hide
          Kathey Marsden added a comment -

          Hi Sunitha,

          Looking at your diff I understand why the first @see was taken out because it was not in a javadoc comment,
          but these two were less clear to me.

          It seems like it would be good instead to keep the @see but use the
          @see #method(Type argname, Type argname,...) format for these two:

          @@ -807,7 +807,7 @@

          • return the security mechanism
          • if security mechanism has not been set explicitly on datasource
          • then upgrade the security mechanism to a more secure one if possible
          • * @see #getUpgradedSecurityMechanism()
            + * See getUpgradedSecurityMechanism()
          • @return the security mechanism
            */
            public short getSecurityMechanism() {
            @@ -819,7 +819,7 @@
          • if security mechanism has not been set explicitly on datasource
          • then upgrade the security mechanism to a more secure one if possible
          • @param password password of user
          • * @see #getUpgradedSecurityMechanism()
            + * See getUpgradedSecurityMechanism()
          • @return the security mechanism
            */
            public short getSecurityMechanism(String password) {
          Show
          Kathey Marsden added a comment - Hi Sunitha, Looking at your diff I understand why the first @see was taken out because it was not in a javadoc comment, but these two were less clear to me. It seems like it would be good instead to keep the @see but use the @see #method(Type argname, Type argname,...) format for these two: @@ -807,7 +807,7 @@ return the security mechanism if security mechanism has not been set explicitly on datasource then upgrade the security mechanism to a more secure one if possible * @see #getUpgradedSecurityMechanism() + * See getUpgradedSecurityMechanism() @return the security mechanism */ public short getSecurityMechanism() { @@ -819,7 +819,7 @@ if security mechanism has not been set explicitly on datasource then upgrade the security mechanism to a more secure one if possible @param password password of user * @see #getUpgradedSecurityMechanism() + * See getUpgradedSecurityMechanism() @return the security mechanism */ public short getSecurityMechanism(String password) {
          Hide
          Sunitha Kambhampati added a comment -

          d962_javadoc.diff.txt patch to fix javadoc warnings in ClientBaseDataSource.

          I ran javadoc and I did a successful build (clobber and ant all). I'd appreciate it a committer could commit this. Thanks.

          Thanks Deepa for reporting this.

          Show
          Sunitha Kambhampati added a comment - d962_javadoc.diff.txt patch to fix javadoc warnings in ClientBaseDataSource. I ran javadoc and I did a successful build (clobber and ant all). I'd appreciate it a committer could commit this. Thanks. Thanks Deepa for reporting this.
          Hide
          Kathey Marsden added a comment -

          Checked this into the trunk:

          Date: Thu Mar 16 17:11:50 2006
          New Revision: 386501

          URL: http://svn.apache.org/viewcvs?rev=386501&view=rev

          Show
          Kathey Marsden added a comment - Checked this into the trunk: Date: Thu Mar 16 17:11:50 2006 New Revision: 386501 URL: http://svn.apache.org/viewcvs?rev=386501&view=rev
          Hide
          Kathey Marsden added a comment -

          I don't have any more comments on this patch. It looks good to me. Thanks for putting the summary in the test. I think that will really help anyone looking at this in the future. It would be great if someone else could look at this patch too. I will check in first thing tomorrow if we don't get any more comments.

          Thanks

          Kathey

          Show
          Kathey Marsden added a comment - I don't have any more comments on this patch. It looks good to me. Thanks for putting the summary in the test. I think that will really help anyone looking at this in the future. It would be great if someone else could look at this patch too. I will check in first thing tomorrow if we don't get any more comments. Thanks Kathey
          Hide
          Sunitha Kambhampati added a comment -

          With the patch Derby962.diff.txt, derbyall run finished on linux/ibm142 with the known failures ( SurTest, NSInSameJVM).

          Show
          Sunitha Kambhampati added a comment - With the patch Derby962.diff.txt, derbyall run finished on linux/ibm142 with the known failures ( SurTest, NSInSameJVM).
          Hide
          Sunitha Kambhampati added a comment -

          This issue was blocked by derby-1080. Now that 1080 is committed, I have regenerated the patch for 962 and am attaching Derby962.diff.txt and Derby962.stat.txt.

          The changes in this patch are the same as compared to the changes in Derby962_forreview.txt that were specific to derby 962, except for the following:
          – I have added the table that was in 962_table.txt into the test code per Kathey's comments and also added some comments from the jira to the test code.

          I ran derbynetclientmats and derbynetmats ok on linux/ibm142 with the known failures in Surtest. I ran testSecMec on windows with JCC2.4, JCC2.6 and derbyclient on ibm and sun jvms , versions 131,141,142,15 ok.

          derbyall is still running. I will post results here as they finish.

          Can someone please review this change. Thanks.

          Show
          Sunitha Kambhampati added a comment - This issue was blocked by derby-1080. Now that 1080 is committed, I have regenerated the patch for 962 and am attaching Derby962.diff.txt and Derby962.stat.txt. The changes in this patch are the same as compared to the changes in Derby962_forreview.txt that were specific to derby 962, except for the following: – I have added the table that was in 962_table.txt into the test code per Kathey's comments and also added some comments from the jira to the test code. I ran derbynetclientmats and derbynetmats ok on linux/ibm142 with the known failures in Surtest. I ran testSecMec on windows with JCC2.4, JCC2.6 and derbyclient on ibm and sun jvms , versions 131,141,142,15 ok. derbyall is still running. I will post results here as they finish. Can someone please review this change. Thanks.
          Hide
          Kathey Marsden added a comment -

          Sunitha said:
          >This variable is used to indicate that the security mechanism has not been >set on datasource or connection request. I can change it to >SECMEC_DEFAULT if that is preferred.
          >Its just that SECMEC_DEFAULT seems to suggest that it is the default >security mechanism which it isnt. The default security mechanism for the client is USRIDONL (0x04)

          I tend to think that the default security mechanism is not USRIDONLY but in fact is variable depending on whether password is specified and whether the JVM can support EUSRIDPPWD, but the name as you have it is ok. I don't feel that strongly about it.

          Show
          Kathey Marsden added a comment - Sunitha said: >This variable is used to indicate that the security mechanism has not been >set on datasource or connection request. I can change it to >SECMEC_DEFAULT if that is preferred. >Its just that SECMEC_DEFAULT seems to suggest that it is the default >security mechanism which it isnt. The default security mechanism for the client is USRIDONL (0x04) I tend to think that the default security mechanism is not USRIDONLY but in fact is variable depending on whether password is specified and whether the JVM can support EUSRIDPPWD, but the name as you have it is ok. I don't feel that strongly about it.
          Hide
          Sunitha Kambhampati added a comment -

          This issue requires DERBY-1080 to be fixed. Also both these issues affect one same file so patch for 962 wont cleanly apply for the file (testSecMec.java).

          Show
          Sunitha Kambhampati added a comment - This issue requires DERBY-1080 to be fixed. Also both these issues affect one same file so patch for 962 wont cleanly apply for the file (testSecMec.java).
          Hide
          Kathey Marsden added a comment -

          Thanks Sunitha for working on this issue and working toward a secure network client and server.
          I looked at your table and the code patch diff, but did not apply it because I had trouble doing so, so this review is probably pretty rough.

          Your table is very useful and I think it should be incorporated into the test or code comments. Perhaps the following could be clarified.

          • In your explanation of columns in the table you refer to the columns as a), b) etc. It would be good to put those letters in the column headers.
          • In your explanations section also list how the numeric values map to the security mechanisms for reference.
            It is further down on the page, but I noticed that after loooking them up.
          • The first section of the table is for the case where no security mechanism is specified. It would be good to call that out in a header as you do before the other sections of the table.

          In the code, I am unsure about the impact of adding this code to the static initializer block. I know you had asked about it earlier and I wish I had insight to the implications but just don't. Hopefully someone else does.

          static
          + {
          + try
          +

          { + // The EncryptionManager class will instantiate objects of the required + // security algorithms that are needed for EUSRIDPWD + // An exception will be thrown if support is not available + // in the JCE implementation in the JVM in which the client + // is loaded. + new org.apache.derby.client.am.EncryptionManager(null); + SUPPORTS_EUSRIDPWD = true; + }

          catch(Exception e)
          +

          { + // if an exception is thrown, ignore exception. + // set SUPPORTS_EUSRIDPWD to false indicating that the client + // does not support EUSRIDPWD security mechanism + SUPPORTS_EUSRIDPWD = false; + }

          + }

          Maybe it would be good to change SECMEC_HAS_NOT_EXPLICITLY_SET to something like SECMEC_DEFAULT for clarification. Something about the negatives in variable names always confuses me.

          Kathey

          Show
          Kathey Marsden added a comment - Thanks Sunitha for working on this issue and working toward a secure network client and server. I looked at your table and the code patch diff, but did not apply it because I had trouble doing so, so this review is probably pretty rough. Your table is very useful and I think it should be incorporated into the test or code comments. Perhaps the following could be clarified. In your explanation of columns in the table you refer to the columns as a), b) etc. It would be good to put those letters in the column headers. In your explanations section also list how the numeric values map to the security mechanisms for reference. It is further down on the page, but I noticed that after loooking them up. The first section of the table is for the case where no security mechanism is specified. It would be good to call that out in a header as you do before the other sections of the table. In the code, I am unsure about the impact of adding this code to the static initializer block. I know you had asked about it earlier and I wish I had insight to the implications but just don't. Hopefully someone else does. static + { + try + { + // The EncryptionManager class will instantiate objects of the required + // security algorithms that are needed for EUSRIDPWD + // An exception will be thrown if support is not available + // in the JCE implementation in the JVM in which the client + // is loaded. + new org.apache.derby.client.am.EncryptionManager(null); + SUPPORTS_EUSRIDPWD = true; + } catch(Exception e) + { + // if an exception is thrown, ignore exception. + // set SUPPORTS_EUSRIDPWD to false indicating that the client + // does not support EUSRIDPWD security mechanism + SUPPORTS_EUSRIDPWD = false; + } + } Maybe it would be good to change SECMEC_HAS_NOT_EXPLICITLY_SET to something like SECMEC_DEFAULT for clarification. Something about the negatives in variable names always confuses me. Kathey
          Hide
          Sunitha Kambhampati added a comment -

          This patch 'Derby962.forreview.diff.txt' is a patch for review. This patch needs derby 1080 for it to work. Also there is one testfile which is common between the derby-1080 and this patch and hence it is likely this patch may not apply cleanly once derby1080 gets reviewed and committed. I generated the diff keeping the changes of derby1080 for the test file (derbynet/testSecMec.java).

          This patch 'Derby962.forreview.diff.txt' improves the upgrade security mechanism logic to do the following.

          1. If securityMechanism is explicitly specified in the connection request then client will not override it.
          2. Dynamically figure out if the jvm in which the client is loaded, supports encrypted userid and
          password security (EUSRIDPWD) or not and use this information to upgrade to a more secure default
          security mechanism.
          3. Thus if user has not specified the security mechanism, in that case the client will try to see if
          it can upgrade the security mechanism and use the new upgraded security mechanism for connection to the server.

          Logic in ClientBaseDataSource#getUpgradedSecurityMechanism()
          + * This method has logic to upgrade security mechanism to a better (more secure) one
          + * if it is possible. Currently derby server only has support for USRIDPWD,USRIDONL,
          + * EUSRIDPWD and this method only considers these possibilities.
          + * USRIDPWD, EUSRIDPWD require a password, USRIDONL is the only security mechanism
          + * which does not require password.
          + * 1. if password is not available, then security mechanism possible is USRIDONL
          + * 2. if password is available, if client supports EUSRIDPWD, then EUSRIDPWD is
          + * returned
          + * 3. if password is available, if client does not support EUSRIDPWD, then USRIDPWD
          + * is returned.

          Testing:
          – Added tests with possible permutations for user, password and security mechanism on a connection request.
          see derbynet/testSecMec.java#testAllCombinationsOfUserPasswordSecMecInput()

          I have attached a table to this jira entry (962_table.txt) that gives information about what security mechanism the client sends to the server on different possible inputs.

          – Ran derbyall on linux/ibm142 ok with known failures.
          – Ran derbynet/testSecMec.java on windows with sane classes for both derbynet(JCC2.4 and JCC2.6)
          /derbynetclientmats with ibm131/ibm15/jdk131/jdk15/ibm142/jdk142.

          Please note: this patch depends and requires fix for derby1080. Most likely when 1080 gets reviewed and committed, this patch may not cleanly apply.

          Can someone please review this change. Thanks.

          Show
          Sunitha Kambhampati added a comment - This patch 'Derby962.forreview.diff.txt' is a patch for review. This patch needs derby 1080 for it to work. Also there is one testfile which is common between the derby-1080 and this patch and hence it is likely this patch may not apply cleanly once derby1080 gets reviewed and committed. I generated the diff keeping the changes of derby1080 for the test file (derbynet/testSecMec.java). This patch 'Derby962.forreview.diff.txt' improves the upgrade security mechanism logic to do the following. 1. If securityMechanism is explicitly specified in the connection request then client will not override it. 2. Dynamically figure out if the jvm in which the client is loaded, supports encrypted userid and password security (EUSRIDPWD) or not and use this information to upgrade to a more secure default security mechanism. 3. Thus if user has not specified the security mechanism, in that case the client will try to see if it can upgrade the security mechanism and use the new upgraded security mechanism for connection to the server. Logic in ClientBaseDataSource#getUpgradedSecurityMechanism() + * This method has logic to upgrade security mechanism to a better (more secure) one + * if it is possible. Currently derby server only has support for USRIDPWD,USRIDONL, + * EUSRIDPWD and this method only considers these possibilities. + * USRIDPWD, EUSRIDPWD require a password, USRIDONL is the only security mechanism + * which does not require password. + * 1. if password is not available, then security mechanism possible is USRIDONL + * 2. if password is available, if client supports EUSRIDPWD, then EUSRIDPWD is + * returned + * 3. if password is available, if client does not support EUSRIDPWD, then USRIDPWD + * is returned. Testing: – Added tests with possible permutations for user, password and security mechanism on a connection request. see derbynet/testSecMec.java#testAllCombinationsOfUserPasswordSecMecInput() I have attached a table to this jira entry (962_table.txt) that gives information about what security mechanism the client sends to the server on different possible inputs. – Ran derbyall on linux/ibm142 ok with known failures. – Ran derbynet/testSecMec.java on windows with sane classes for both derbynet(JCC2.4 and JCC2.6) /derbynetclientmats with ibm131/ibm15/jdk131/jdk15/ibm142/jdk142. Please note: this patch depends and requires fix for derby1080. Most likely when 1080 gets reviewed and committed, this patch may not cleanly apply. Can someone please review this change. Thanks.
          Hide
          Sunitha Kambhampati added a comment -

          Table with combinations of userid/password/security mechanism and what client sends to the server. Uploading now, so I can include this link in the testcase comment..

          Show
          Sunitha Kambhampati added a comment - Table with combinations of userid/password/security mechanism and what client sends to the server. Uploading now, so I can include this link in the testcase comment..
          Hide
          Sunitha Kambhampati added a comment -

          I just started looking at this issue on how to know if the jvm in which the client is running can support encrypted userid and password mechanism or not; to decide if we can upgrade the default security mechanism.

          I wanted to share some thoughts I have, so I could get early feedback from the list.

          Current client driver supports encrypted userid/password (EUSRIDPWD) via the use of DH key-agreement protocol - however current Open Group DRDA specifications imposes small prime and base generator values (256 bits) that prevents other JCE's (apt from ibm jce) to be used as java cryptography providers.

          – org.apache.derby.client.am.EncryptionManager (EM) constructor is responsible for instantiating the appropriate Provider and the KeyPairGenerator. The Sun JCE throws java.security.InvalidAlgorithmParameterException exception when trying to use the 256bits prime.

          I think we can conclude if the EM throws an exception, then the JCE doesnt support the required algorithms.
          => An exception from this constructor indicates that it is not possible to use encrypted userid/password.

          The next step seems to me to decide where to put the call to new EncryptionManager(EM)
          #A.Put in static initializer block in ClientBaseDataSource and store the result in a static variable. The ClientBaseDataSource seems to be place where all the url attribute values' gets and sets methods are present. Also the upgrade logic for the security mechanism is in this class.

          something like:
          static boolean SUPPORTS_EUSRIDPWD = false;
          static
          {
          try

          { new org.apache.derby.client.am.EncryptionManager(null); SUPPORTS_EUSRIDPWD = true; }

          catch(Exception e)

          { //ignore }

          }

          ---------------

          #B. Another place this check could go was in the ClientDriver itself since this will be loaded in the JVM. In the static initializer of ClientDriver, new of EM can be done to check if it will go through OK. If so, a static 'protected' variable in ClientDriver can be used to store the state that the driver supports the algorithms required for encrypted userid/password.

          1. Are there any issues with adding code to the static initializer block of the Client Driver. I see the following comment in ClientDriver which sounds a little scary to me.

          static {
          // This may possibly hit the race-condition bug of java 1.1.
          // The Configuration static clause should execute before the following line does.
          if (Configuration.exceptionsOnLoadResources != null)

          { ...... }

          I can see that the Configuration static initializer needs to run before the access to the static variable Configuration.exceptionsOnLoadResources.

          I'm curious and would like to look at it sometime. If someone could point me to some reference of this bug, I'd be grateful. I googled but didnt find any related to the static intializer blocks.
          --------------

          #C Explicitly check the jvm and decide. Not a good way for e.g. if SunJCE supports the DH with 256 bits prime some day, we would have to remember to remove this check that disables encrypted userid/password for this particular JVM.

          I like #A because it seems clean. What do others think ?

          Comments/Thoughts.

          Thanks much,
          Sunitha.

          Show
          Sunitha Kambhampati added a comment - I just started looking at this issue on how to know if the jvm in which the client is running can support encrypted userid and password mechanism or not; to decide if we can upgrade the default security mechanism. I wanted to share some thoughts I have, so I could get early feedback from the list. Current client driver supports encrypted userid/password (EUSRIDPWD) via the use of DH key-agreement protocol - however current Open Group DRDA specifications imposes small prime and base generator values (256 bits) that prevents other JCE's (apt from ibm jce) to be used as java cryptography providers. – org.apache.derby.client.am.EncryptionManager (EM) constructor is responsible for instantiating the appropriate Provider and the KeyPairGenerator. The Sun JCE throws java.security.InvalidAlgorithmParameterException exception when trying to use the 256bits prime. I think we can conclude if the EM throws an exception, then the JCE doesnt support the required algorithms. => An exception from this constructor indicates that it is not possible to use encrypted userid/password. The next step seems to me to decide where to put the call to new EncryptionManager(EM) #A.Put in static initializer block in ClientBaseDataSource and store the result in a static variable. The ClientBaseDataSource seems to be place where all the url attribute values' gets and sets methods are present. Also the upgrade logic for the security mechanism is in this class. something like: static boolean SUPPORTS_EUSRIDPWD = false; static { try { new org.apache.derby.client.am.EncryptionManager(null); SUPPORTS_EUSRIDPWD = true; } catch(Exception e) { //ignore } } --------------- #B. Another place this check could go was in the ClientDriver itself since this will be loaded in the JVM. In the static initializer of ClientDriver, new of EM can be done to check if it will go through OK. If so, a static 'protected' variable in ClientDriver can be used to store the state that the driver supports the algorithms required for encrypted userid/password. 1. Are there any issues with adding code to the static initializer block of the Client Driver. I see the following comment in ClientDriver which sounds a little scary to me. static { // This may possibly hit the race-condition bug of java 1.1. // The Configuration static clause should execute before the following line does. if (Configuration.exceptionsOnLoadResources != null) { ...... } I can see that the Configuration static initializer needs to run before the access to the static variable Configuration.exceptionsOnLoadResources. I'm curious and would like to look at it sometime. If someone could point me to some reference of this bug, I'd be grateful. I googled but didnt find any related to the static intializer blocks. -------------- #C Explicitly check the jvm and decide. Not a good way for e.g. if SunJCE supports the DH with 256 bits prime some day, we would have to remember to remove this check that disables encrypted userid/password for this particular JVM. I like #A because it seems clean. What do others think ? Comments/Thoughts. Thanks much, Sunitha.
          Hide
          Bryan Pendleton added a comment -

          I agree, Sunitha. If the user says something like:

          connect 'jdbc:derby://localhost:1527/testdb;create=true;securityMechanism=4;user=bryan;password=bryan';

          we should not quietly change the securityMechanism to 3 and quietly send the password in the clear. That's a bad default to have.

          The user has given us conflicting information, and we should ask them to either change the securityMechanism to one which supports a password, or remove the password.

          I can see the appeal of quietly upgrading to a secure securityMechanism (one which doesn't expose the password over the wire), but in general my preference would be to give them an error saying that their request is ambiguous, rather than trying to guess what sort of alternate securityMechanism they may have wanted.

          Show
          Bryan Pendleton added a comment - I agree, Sunitha. If the user says something like: connect 'jdbc:derby://localhost:1527/testdb;create=true;securityMechanism=4;user=bryan;password=bryan'; we should not quietly change the securityMechanism to 3 and quietly send the password in the clear. That's a bad default to have. The user has given us conflicting information, and we should ask them to either change the securityMechanism to one which supports a password, or remove the password. I can see the appeal of quietly upgrading to a secure securityMechanism (one which doesn't expose the password over the wire), but in general my preference would be to give them an error saying that their request is ambiguous, rather than trying to guess what sort of alternate securityMechanism they may have wanted.
          Hide
          Sunitha Kambhampati added a comment -

          The current behavior even if the security mechanism is explicitly set in the connection url, the upgrade is done-- should this happen.

          I think we should not upgrade (override) if user has explicitly set the security mechanism. Thoughts ?

          see ClientBaseDataSource# getUpgradedSecurityMechanism() for code where the upgrade from USRIDONL to USRIDPWD is done.

          Show
          Sunitha Kambhampati added a comment - The current behavior even if the security mechanism is explicitly set in the connection url, the upgrade is done-- should this happen. I think we should not upgrade (override) if user has explicitly set the security mechanism. Thoughts ? see ClientBaseDataSource# getUpgradedSecurityMechanism() for code where the upgrade from USRIDONL to USRIDPWD is done.

            People

            • Assignee:
              Sunitha Kambhampati
              Reporter:
              Sunitha Kambhampati
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Development