Closed peter279k closed 4 years ago
And my phive.xml
is as follows:
?xml version="1.0" encoding="UTF-8"?>
<phive xmlns="https://phar.io/phive">
<phar name="phpunit" version="7.3" installed="7.3.5" location="./tools/phpunit" copy="false"/>
<phar name="phpcs" version="^3.5.2" installed="3.5.4" location="./tools/phpcs" copy="true"/>
<phar name="phpstan" version="^0.12.2" installed="0.12.9" location="./tools/phpstan" copy="true"/>
</phive>
To dig this issue, I also use development repository and add some output functions before making implode
function call.
.......
public function getStatusMessage(): string {
var_dump(gettype($this->verificationData['status']));
var_dump($this->verificationData['status']);
return \implode("\n", $this->verificationData['status']);
}
.......
After I use the repository on master
development branch, I found $this->verificationData['status']
variable is as follows:
/path/to/phive/src/services/signature/gpg/GnupgVerificationResult.php:27:
string(7) "integer"
/path/to/phive/src/services/signature/gpg/GnupgVerificationResult.php:28:
int(9)
Thanks for the report. It took me a while to reproduce this. It seems like this only happens with ext/gnupg
installed.
Your fix though is not addressing the underlying issue. The problem seems to lay in our wrapper implementation which deviates from the ext/gnugpg
results:
Our Wrapper:
array(1) {
[0]=>
array(5) {
["fingerprint"]=>
string(16) "4AA394086372C20A"
["validity"]=>
int(0)
["timestamp"]=>
string(10) "1536419702"
["status"]=>
array(3) {
[0]=>
string(15) "[GNUPG:] NEWSIG"
[1]=>
string(55) "[GNUPG:] ERRSIG 4AA394086372C20A 1 10 00 1536419702 9 -"
[2]=>
string(35) "[GNUPG:] NO_PUBKEY 4AA394086372C20A"
}
["summary"]=>
int(128)
}
}
ext/gnupg
:
array(1) {
[0]=>
array(5) {
["fingerprint"]=>
string(16) "4AA394086372C20A"
["validity"]=>
int(0)
["timestamp"]=>
int(1536419702)
["status"]=>
int(9)
["summary"]=>
int(128)
}
}
Apart from the maybe non obvious type confusion for the timestamp, the status element is completely wrong. This clearly qualifies as a bug. But not in phive
but the gnupg wrapper. I'll open/move this issue over to it.
Thanks for your time to dig issue in advanced. And it seems that the gnupg
result is not different.
I think it can let these results be consistency and this issue will be fixed :).
@theseer, do you have any possible solution to resolve this issue?
If possible, I think you can describe possible solution approach and I can work on that and create related PR about this issue :).
Sure.
Disable ext/gnupg
until fix is released.
It's a two (maybe three) step thing:
The result array returned in the phar-io/gnupg
wrapper's ::verify()
method needs to be adjusted to be identical to the one from ext/gnupg
. My current assumption is that the status
property equals the gnupg return code. But that's not been properly checked yet.
We use the status
property to show the raw output on error. That's obviously wrong as ext/gnupg
only returns an int
here and our wrapper puts all the text output into it. We need to adjust the error handling not to use the status
property. Potentially by having a map that translates the error code into a string (https://github.com/phar-io/gnupg/issues/2#issuecomment-623189928).
~(optional) If we can find a way for ext/gnupg
to return the raw output to be more verbose, we should implement an identical api in our wrapper to get the output the same way. And add the call to our error reporting.~ Not possible
- (optional) If we can find a way for ext/gnupg to return the raw output to be more verbose, we should implement an identical api in our wrapper to get the output the same way. And add the call to our error reporting.
I think it's not possible after looking at the official gnupg function usage reference.
I also prefer using the method 2 and provide some other ways to resolve this issue:
Create new class named StatusHandler.php
and convert status code to current message with GnuPG const status message lists.
Create new method named convertStatus
inside harIo\GnuPG\GnuPG
class. And do same work as above approach.
I think it would be quick to resolve this issue and it's very similar with method 2 you mention.
@theseer, do you have any suggestion about this :)?
I guess it becomes more and more obvious that trying to provide a drop-in alternative rather than an actual wrapper with some additional logic isn't as beneficial as I believed when the library got created.
If - at least for now - we keep the approach of mimicking the ext/gnupg
API, the only change needed here is the ensure that we return the correct status code in our cli wrapper. So basically, only step 1 is part of this project.
The step 2 is within phar-io/phive
. I think we can create a sort of value object GnupgStatus
, that get's the original status code as int
supplied via constructor and has asString()
translating it into human readable form. We can of course also provide asInt()
. And, for convenience, an isSuccess
to internalize that decision.
I removed the optional step 3.
Given for all the cases I could come up with the status and return code are identical and match what the linked gpgme header file lists, I'll assume that's correct and implement it that way.
Since ext/gnupg
has ::geterror
I'll implement that as the hook for getting the error text.
Thanks for the research!
@theseer, thanks for your commit.
After using the native PHP GnuPG::geterror()
method, it cannot get current status message:
Here are my code snippets:
use PharIo\GnuPG\Factory;
use PharIo\FileSystem\Directory;
$executor = new Factory();
$gnupg = $executor->createGnuPG(new Directory('/home/user/.gnupg'));
$result = $gnupg->verify('9D8A98B29B2D5D79', file_get_contents('./phive.phar.asc'));
var_dump($result);
var_dump($gnupg->geterror());
/data/gnupg/test.php:15:
array(1) {
[0] =>
array(5) {
'fingerprint' =>
string(16) "9D8A98B29B2D5D79"
'validity' =>
int(0)
'timestamp' =>
int(1572391508)
'status' =>
int(9)
'summary' =>
int(128)
}
}
/data/gnupg/test.php:16:
bool(false)
@theseer, after doing more tests about native GnuPG::geterror
method, it seems that this method is only affected by some methods are "failed" or has exception message.
For example, turning off the GnuPG error mode and using error PGP SIGNATURE via GnuPG::verify
method.
These code snippets are as follows:
use PharIo\FileSystem\Directory;
use PharIo\GnuPG\Factory;
$executor = new Factory();
$gnupg = $executor->createGnuPG(new Directory('/home/user/.gnupg'));
$gnupg->seterrormode(\Gnupg::ERROR_SILENT);
$result = $gnupg->verify('9D8A98B29B2D5D79', '1234');
var_dump($result);
var_dump($gnupg->geterror());
/data/gnupg/test.php:16:
bool(false)
/data/gnupg/test.php:17:
string(13) "verify failed"
I'm not sure what you are trying to tell me here:
That I have to change the error mode in the factory for the ext/gnupg
so
gnupg::geterror
works?
That the wrapper isn't working?
Something else? :)
@theseer, thanks for your reply.
I mean the GnuPG::geterror
wrapper behavior is different from ext/gnupg::geterror
method.
I just use the Factory
to create my GnuPG
wrapper quickly. Forgive me that this approach lets you misunderstand what I mean :cry: ...
I think this latest commit cannot resolve this issue...
No worries.
Let's sort things out.
The actual implode call is (or was rather) not part of this repository - it happened in phar-io/phive
. But phive
relied on the status
returned by our wrapper to be an array
of string
s rather than the int
as it should have been because ext/gnupg
returns an int
in status
.
The wrapper code has been changed to now have the return code of the underlying gnupg run as status
.
This change of course theoretically broke phive
to now neither work with the extension nor the cli wrapper. So phive
was changed to not do the implode
call anymore but use the ErrorString
class (https://github.com/phar-io/phive/blob/master/src/services/signature/gpg/GnupgVerificationResult.php#L29) provided by phar-io/gnupg
.
We actually don't even use the wrapper implementation of geterror
in phive
because I have no means of accessing its instance when we get the result - and don't even need it.
There are two (potential) inconsistencies:
Our implementation maps the "official" error strings from the gnupg source code (see https://github.com/phar-io/gnupg/blob/master/makeErrorCodeMap.sh#L3). The ext/gnupg
extension has hardcoded error strings (for example: https://github.com/php-gnupg/php-gnupg/blob/master/gnupg.c#L1538).
Unless someone feels the urge to grep through the source code of the extension and map out all their error messages with the corresponding code, there is very little chance both implementations return identical strings.
The geterror
implementation is stateful, returning the error string matching the error code of the last whatever was run. While I consider that a very impractical implementation choice (to say the least..), there's not much I can do if the goal of this project is to mimic the API provided.
Now for your input: If I understood correctly, you basically are telling me I should change https://github.com/phar-io/gnupg/blob/master/src/Factory.php#L27 to $gpg->seterrormode(\Gnupg::ERROR_SILENT);
so I'll geterror
will "always" work?
Now for your input: If I understood correctly, you basically are telling me I should change https://github.com/phar-io/gnupg/blob/master/src/Factory.php#L27 to $gpg->seterrormode(\Gnupg::ERROR_SILENT); so I'll geterror will "always" work?
Yes, that's correct.
Our implementation maps the "official" error strings from the gnupg source code (see https://github.com/phar-io/gnupg/blob/master/makeErrorCodeMap.sh#L3). The ext/gnupg extension has hardcoded error strings (for example: https://github.com/php-gnupg/php-gnupg/blob/master/gnupg.c#L1538).
Unless someone feels the urge to grep through the source code of the extension and map out all their error messages with the corresponding code, there is very little chance both implementations return identical strings.
I think we should let ext/gnupg
and PharIo\GnuPG\GnuPG
wrappers about geterror
method behavior be consistency.
Our implementation maps the "official" error strings from the gnupg source code (see https://github.com/phar-io/gnupg/blob/master/makeErrorCodeMap.sh#L3). The ext/gnupg extension has hardcoded error strings (for example: https://github.com/php-gnupg/php-gnupg/blob/master/gnupg.c#L1538).
Unless someone feels the urge to grep through the source code of the extension and map out all their error messages with the corresponding code, there is very little chance both implementations return identical strings.
I think we should let
ext/gnupg
andPharIo\GnuPG\GnuPG
wrappers aboutgeterror
method behavior be consistency.
Fine with me. Do you feel like providing a PR for the map based on the pecl source?
Now for your input: If I understood correctly, you basically are telling me I should change https://github.com/phar-io/gnupg/blob/master/src/Factory.php#L27 to $gpg->seterrormode(\Gnupg::ERROR_SILENT); so I'll geterror will "always" work?
Yes, that's correct.
Okay, can do I guess.
In general: You do agree the problem this ticket was about is solved?
In general: You do agree the problem this ticket was about is solved?
Yes. This issue is resolved, thanks :).
Fine with me. Do you feel like providing a PR for the map based on the pecl source?
Yes. It's correct. We should let GnuPG has detailed status text on PECL source.
@theseer, I also create this issue to make status text consistency.
Thanks for your help again :).
I'm not sure that issue you opened for ext/gnupg
will make sense to them.
What's the "native gpg binary wrapper" you refer to?
I'm not sure that issue you opened for
ext/gnupg
will make sense to them. What's the "native gpg binary wrapper" you refer to?
The "native gpg binary wrapper" is about the gpg
command.
I'm not sure that issue you opened for
ext/gnupg
will make sense to them. What's the "native gpg binary wrapper" you refer to?The "native gpg binary wrapper" is about the
gpg
command.
As in, the gnupg binary called? If so, how? Because merely running gpg
will not generate any structured PHP style output. If you refer to phar-io/gnupg
's call, the resulting array is a result of parsing - and no longer contains the status text blob.
What is it you want them to do?
I hope the parsed verified output should contain status text blob, not just a status code and it can be consistency gpg
command with --verify
execution output.
And the PHP style output is just a example, and I think I should modify them to be general output to be compatible with gpg
binary command executing result.
Reproducing issue
0.13.2
Expected
Actual
After tracing error message output, I think the problematic code snippets are as follows:
https://github.com/phar-io/phive/blob/e75aa29de010ec25f12afcbe242fc2072284f066/src/services/signature/gpg/GnupgVerificationResult.php#L27
And the
$this->verificationData['status']
variable may not be array type.To resolve this issue, I think it should cast the
$this->verificationData['status']
variable toarray
type before making implode function call.