self-service-password icon indicating copy to clipboard operation
self-service-password copied to clipboard

allow more than one mail_attribute value

Open muzzol opened this issue 3 years ago • 25 comments

on one of my setups I use two attributes with mail, one is optional (personalMail) and the other one mandatory (mail).

I would like to use first if found and then second one. something similar to ldap_url attribute:

$mail_attribute = "personalMail mail";

thanks for your time

muzzol avatar Apr 08 '21 10:04 muzzol

Hello,

this is not possible now. It needs some code in htdocs/sendtoken.php

See https://github.com/ltb-project/self-service-password/blob/master/htdocs/sendtoken.php#L120

coudot avatar Apr 08 '21 17:04 coudot

I'm trying to configure this on a fresh test installation and I'm facing some problems.

https://self-service-password.readthedocs.io/en/latest/config_mail.html

docs here refers to $mail_attributes but in config.inc.php I only see $mail_attribute so I guess first one is a typo.

I use $mail_address_use_ldap = true; and I can use $mail_attribute = "mail"; but if I try to configure an array like this $mail_attribute = array('personalMail', 'mail'); I get a mailnomatch error: The email address does not match the submitted user name

and this appears in logs:


[Thu Sep 09 12:28:08.304621 2021] [php7:warn] [pid 15739] [client 172.16.236.12:52060] PHP Warning:  ldap_get_values() expects parameter 3 to be string, array given in /var/www/html/ssp/htdocs/sendtoken.php on line 122, referer: http://xx.xx.xx.xx/ssp/index.php
[Thu Sep 09 12:28:08.304700 2021] [php7:warn] [pid 15739] [client 172.16.236.12:52060] PHP Warning:  count(): Parameter must be an array or an object that implements Countable in /var/www/html/ssp/htdocs/sendtoken.php on line 138, referer: http://xx.xx.xx.xx/ssp/index.php
[Thu Sep 09 12:28:08.304731 2021] [php7:notice] [pid 15739] [client 172.16.236.12:52060] Mail not found for user XXXXX, referer: http://xx.xx.xx.xx/ssp/index.php

Is there any other configuration I'm missing?

let me know if you want me to open a new issue

muzzol avatar Sep 09 '21 10:09 muzzol

Are you using code from master?

coudot avatar Sep 09 '21 11:09 coudot

no, just downloaded zip from GH:

wget https://github.com/ltb-project/self-service-password/archive/refs/tags/v1.4.3.zip

muzzol avatar Sep 09 '21 11:09 muzzol

As you can see, the fix is merged in master and will be available in 1.5

coudot avatar Sep 09 '21 11:09 coudot

@faust64 there will be a need for an upgrade note, as we changed a configuration attribute name

coudot avatar Sep 09 '21 11:09 coudot

oh! I see, I'll try master now to test it. sorry I missed 1.5 target.

muzzol avatar Sep 09 '21 11:09 muzzol

works perfectly!

thanks for your time :)

muzzol avatar Sep 09 '21 12:09 muzzol

sorry to resurface this, but I'm having strange behaviour.

I use two attributes: $mail_attributes = array('personalMail', 'mail');

first one is not always present but it should be used if exists. thing is I'm getting an error if first attribute is empty:

[Fri Sep 10 11:30:34.848908 2021] [php7:warn] [pid 17564] [client xx:54702] PHP Warning:  ldap_get_values(): Cannot get the value(s) of attribute Decoding error in /var/www/html/clau/htdocs/sendtoken.php on line 123, referer: https://xx/clau/index.php
[Fri Sep 10 11:30:34.848999 2021] [php7:warn] [pid 17564] [client xx:54702] PHP Warning:  count(): Parameter must be an array or an object that implements Countable in /var/www/html/clau/htdocs/sendtoken.php on line 137, referer: https://xx/clau/index.php

If I change the order to $mail_attributes = array( 'mail', 'personalMail'); it works, but I need it the other way around.

can you please check it?

I'm using master downloaded yesterday

muzzol avatar Sep 10 '21 09:09 muzzol

Line 123 from sendtoken.php would be some $mailValues = ldap_get_values($ldap, $entry, $mail_attribute); I'm not sure what's going on. Sounds like an issue with that ldap function -- or our input...

Have you looked at this: https://www.php.net/manual/en/function.ldap-get-values-len.php#103586 Or that one: https://stackoverflow.com/questions/32630706/php-ldap-get-values-for-more-than-1-value#comment53112241_32630706

Sounds like that error would show when requesting some invalid attribute name, somehow?

What's that personalMail attribute? Are you sure it's there? Check your schemas, maybe? Can you query its value using ldapsearch, and your self-service-password bind credentials?

If nothing helps, we might try to patch sendtoken.php, such as:

diff --git a/htdocs/sendtoken.php b/htdocs/sendtoken.php
index b7dac98..a436735 100644
--- a/htdocs/sendtoken.php
+++ b/htdocs/sendtoken.php
@@ -120,7 +120,9 @@ if ( $result === "" ) {
         # Compare mail values
         for ($match = false, $i = 0; $i < sizeof($mail_attributes) and ! $match; $i++) {
             $mail_attribute = $mail_attributes[$i];
-            $mailValues = ldap_get_values($ldap, $entry, $mail_attribute);
+           if (($mailValues = ldap_get_values($ldap, $entry, $mail_attribute)) == false) {
+               die("ldap_get_values error: ".ldap_error($ldap));
+           }
             unset($mailValues["count"]);
             if (! $mail_address_use_ldap) {
                 # Match with user submitted values
syn@sisyphe:~/git/worteks/self-service-password$  

faust64 avatar Sep 14 '21 18:09 faust64

I don't really know about ldap functions, but the problems seems to be that it doesn'l like when one of the configured attributes returns no value, and for me it seems that it should be a very common scenario.

isn't there any more arrays that one of the elements return no value in the code?

my two attributes are mail and XXXpersonalMail. first one is standar, second one is a custom one with the name of a company (XXX) and isn't always there, some user objects have it and others don't.

sorry I can't be more helpfull here, I'll test it right away any solution you give me.

muzzol avatar Sep 15 '21 13:09 muzzol

When ldap_get_values doesn't find anything for a given attribute, it doesn't throw an error. You would get an object, with a key count, and its value: 0. There's something wrong going on. But I doubt it has to do with attribute not being present.

There's nothing much we can do, without more context on what you're querying. At that stage, ldap_get_values inspects the object returned by your LDAP/AD. Maybe the changes I pointed in my previous post would tell us more about what's going on. Not sure.

Otherwise, https://www.php.net/manual/en/function.ldap-get-values-len.php#103586 says

After using PHP to list the attributes of a particular record I noticed that the attribute userCertificate wasn't listed simply as userCertificate but userCertificate;binary instead.

Though this may not be your case, we could try to dump any attribute name returned for a given user object. Might tell us more about what's going on.

faust64 avatar Sep 15 '21 14:09 faust64

ok, I've found a very easy way to reproduce it, just use description as your other mail attribute:

$mail_attributes = array('description','mail');

if both attributtes are present it works. if first attribute is present it works, if first atribute is empty then it gives the error. so is not really related to my custom schema, it fails with any text attribute.

here's the log:


[Wed Sep 15 21:40:42.211089 2021] [php7:warn] [pid 24487] [client 172.26.69.1:33626] PHP Warning:  ldap_get_values(): Cannot get the value(s) of attribute Decoding error in /var/www/html/clautest/htdocs/sendtoken.php on line 123, referer: http://172.26.66.17/clautest/index.php
[Wed Sep 15 21:40:42.211122 2021] [php7:warn] [pid 24487] [client 172.26.69.1:33626] PHP Warning:  count(): Parameter must be an array or an object that implements Countable in /var/www/html/clautest/htdocs/sendtoken.php on line 137, referer: http://172.26.66.17/clautest/index.php
[Wed Sep 15 21:40:42.461256 2021] [php7:notice] [pid 24487] [client 172.26.69.1:33626] Send reset URL HIDDEN, referer: http://172.26.66.17/clautest/index.php
[Wed Sep 15 21:40:42.461274 2021] [php7:notice] [pid 24487] [client 172.26.69.1:33626] send_mail: no mail given, exiting..., referer: http://172.26.66.17/clautest/index.php
[Wed Sep 15 21:40:42.461280 2021] [php7:notice] [pid 24487] [client 172.26.69.1:33626] Error while sending token to  (user pepet10), referer: http://172.26.66.17/clautest/index.php


muzzol avatar Sep 15 '21 19:09 muzzol

any updates on this issue?

muzzol avatar Sep 27 '21 11:09 muzzol

Could you try this patch:

diff --git a/htdocs/sendtoken.php b/htdocs/sendtoken.php
index b7dac98..a1ac1e2 100644
--- a/htdocs/sendtoken.php
+++ b/htdocs/sendtoken.php
@@ -120,6 +120,7 @@ if ( $result === "" ) {
         # Compare mail values
         for ($match = false, $i = 0; $i < sizeof($mail_attributes) and ! $match; $i++) {
             $mail_attribute = $mail_attributes[$i];
+            if ( isset $entry[$mail_attribute] ) {
             $mailValues = ldap_get_values($ldap, $entry, $mail_attribute);
             unset($mailValues["count"]);
             if (! $mail_address_use_ldap) {
@@ -143,6 +144,7 @@ if ( $result === "" ) {
                     $match = true;
                 }
             }
+            }
         }
 
         if (! $match) {

coudot avatar Sep 27 '21 14:09 coudot

there was some missing parentheses here:

if ( isset ($entry[$mail_attribute] )) {

anyway, it doesn't work, I get Mail not found for user XXX

muzzol avatar Sep 28 '21 10:09 muzzol

This one should work:

diff --git a/htdocs/sendtoken.php b/htdocs/sendtoken.php
index b7dac98..e904ba0 100644
--- a/htdocs/sendtoken.php
+++ b/htdocs/sendtoken.php
@@ -121,6 +121,7 @@ if ( $result === "" ) {
         for ($match = false, $i = 0; $i < sizeof($mail_attributes) and ! $match; $i++) {
             $mail_attribute = $mail_attributes[$i];
             $mailValues = ldap_get_values($ldap, $entry, $mail_attribute);
+            if ($mailValues) {
             unset($mailValues["count"]);
             if (! $mail_address_use_ldap) {
                 # Match with user submitted values
@@ -143,6 +144,7 @@ if ( $result === "" ) {
                     $match = true;
                 }
             }
+            }
         }
 
         if (! $match) {

coudot avatar Sep 28 '21 16:09 coudot

it works!

the only thing is that if first attribute is empty I receive a warning:

PHP Warning: ldap_get_values(): Cannot get the value(s) of attribute Decoding error in /var/www/html/clautest/htdocs/sendtoken.php on line 123

nothing critical for me.

muzzol avatar Sep 29 '21 06:09 muzzol

Indeed, there is a warning. To avoid it we need to first check if the attribute is present in the entry before calling ldap_get_values. I'll see what we can do.

coudot avatar Sep 29 '21 08:09 coudot

@muzzol empty attributes are very uncommon and should be avoided since somehow a undefined behavior, you will hit many other problems with various ldap libraries. To be on the safe side empty attributes should just be removed fully.

i believe code that refused it with LDAP_DECODING_ERROR is in ( https://git.openldap.org/openldap/openldap.git ) in ldap_get_values_len function of getvalues.c code.

	/* 
	 * if we get this far, we've found the attribute and are sitting
	 * just before the set of values.
	 */

	if ( ber_scanf( &ber, "[V]", &vals ) == LBER_ERROR ) {
		ld->ld_errno = LDAP_DECODING_ERROR;
		return( NULL );
	}

where a set of octet string sequence is expected, and something else is found. ( see man ber_scanf ).

I fear that to remove your error, you will have to patch yourself the openldap C library used to comple php ldap extension.

How did you create those empty attributes ?

artlog avatar Jul 02 '22 12:07 artlog

@artlog the issue is not that the attribute exist and is empty, which is indeed not standard. Here the attribute does not exist in the entry, but our code does not test this before reading the value. So the solution to avoid these warning are to test if the attribute exist in the entry before calling ldap_get_values

coudot avatar Jul 04 '22 13:07 coudot

Another idea to ease the migration between 1.4 and 1.5: if mail_attributes is not defined and mail_attribute exists, then initialize mail_attributes like this:

$mail_attributes = array($mail_attribute);

Same should be done for mobile (#658)

coudot avatar Jul 04 '22 13:07 coudot

@muzzol empty attributes are very uncommon and should be avoided since somehow a undefined behavior, you will hit many other problems with various ldap libraries. To be on the safe side empty attributes should just be removed fully.

as @coudot pointed out, my problem was with different attributes that can handle same information.

I think is a quite common issue on big companies, for example with mail (personal mail, recovery password mail), and telephone (extension, mobile, personal phone).

The way @coudot solved it was perfect for me, if one object is not there, just ignore it and go for the next one.

I'm not really sure what's your problem here, feel free to be more specific about your own issue so we can help.

muzzol avatar Jul 05 '22 10:07 muzzol

thanks @muzzol & @coudot , i did reproduce it when referencing an un existing attribue ( ie description ). As @coudot wrote, actual testing that attribute exists withing ldap search entry content is the way to handle it properly, i will work on it.

artlog avatar Jul 08 '22 09:07 artlog

Should be fixed with #676, if you have some time to test

coudot avatar Jul 12 '22 15:07 coudot

No feedback, works on my side, so I close.

coudot avatar Aug 23 '22 12:08 coudot