]> git.michaelhowe.org Git - packages/libl/liblemonldap-ng-portal-auth-my-kerberos-perl.git/commitdiff
Fudge things by including Password::My::KerberosAuth too master
authorMichael Howe <michael@michaelhowe.org>
Mon, 31 May 2021 19:12:24 +0000 (20:12 +0100)
committerMichael Howe <michael@michaelhowe.org>
Mon, 31 May 2021 19:12:24 +0000 (20:12 +0100)
This does password changing

Should probably name the package better, but that can go on the todo
list...

debian/changelog
lib/Lemonldap/NG/Portal/Password/My/KerberosAuth.pm [new file with mode: 0644]

index 4ac4756456dbe7ef81ae29daf5e09a65790bb6af..f5d93127e364402a16e1cbb4b1d0b8d095351e07 100644 (file)
@@ -1,7 +1,8 @@
-liblemonldap-ng-portal-auth-my-kerberosauth-perl (1.0~test.1) unstable; urgency=medium
+liblemonldap-ng-portal-auth-my-kerberosauth-perl (1.0~test.2) unstable; urgency=medium
 
   * Initial Release.
   * Rename because there are collisions with the Kerberos name, so use
     KerberosAuth instead
+  * Include Password::My::KerberosAuth too, for now
 
  -- Michael Howe <michael@michaelhowe.org>  Tue, 19 May 2020 16:13:11 +0100
diff --git a/lib/Lemonldap/NG/Portal/Password/My/KerberosAuth.pm b/lib/Lemonldap/NG/Portal/Password/My/KerberosAuth.pm
new file mode 100644 (file)
index 0000000..9094d7b
--- /dev/null
@@ -0,0 +1,158 @@
+package Lemonldap::NG::Portal::Password::My::KerberosAuth;
+
+use strict;
+use Mouse;
+use Expect;
+use Lemonldap::NG::Portal::Main::Constants qw(
+  PE_OK
+  PE_ERROR
+  PE_BADOLDPASSWORD
+  PE_PASSWORD_OK
+  PE_PASSWORD_MISMATCH
+  PE_PP_PASSWORD_TOO_SHORT
+  PE_PP_NOT_ALLOWED_CHARACTER
+  PE_PP_NOT_ALLOWED_CHARACTERS
+  PE_PP_MUST_SUPPLY_OLD_PASSWORD
+  PE_PP_INSUFFICIENT_PASSWORD_QUALITY
+  PE_PP_PASSWORD_IN_HISTORY
+);
+
+extends 'Lemonldap::NG::Portal::Password::Base';
+
+our $VERSION = '0.1.0';
+
+sub init {
+    my ($self) = @_;
+    return $self->SUPER::init;
+}
+
+sub confirm {
+    return 1;
+}
+
+sub modifyPassword {
+    my ( $self, $req, $pwd ) = @_;
+    my $kpasswd = "/usr/bin/kpasswd";
+
+    my $exp = new Expect;
+    $exp->raw_pty(1);
+
+    $exp->spawn($kpasswd, $req->{user});
+    my $r1 = $exp->expect(5, "Password for " . $req->{user});
+    unless( $r1 == 1 ){
+        $exp->hard_close();
+        $self->logger->error("kpasswd did not prompt for credentials for " . $req->{user});
+        return PE_ERROR;
+    }
+
+    $exp->send($req->data->{oldpassword} . "\n");
+    my @r2 = $exp->expect(5, "Enter new password: ", "Preauthentication failed getting initial ticket");
+    if( $r2[0] != 1 ){
+        $exp->hard_close();
+        if( $r2[0] == 2 ){
+            $self->logger->error("kpasswd failed for " . $req->{user} . ": incorrect old password" );
+            return PE_BADOLDPASSWORD;
+        } else {
+            $self->logger->error("kpasswd failed after prompt for old password for " . $req->{user} . ": " . join(' | ', @r2[0,2-4]) );
+            return PE_ERROR;
+        }
+    }
+    $exp->send($pwd . "\n");
+    my @r3 = $exp->expect(5, "Enter it again: ");
+    unless ( @r3[0] == 1 ){
+        $exp->hard_close();
+        $self->logger->error("kpasswd failed for " . $req->{user} . ": " . join(' | ', @r3[0,2-4]) );
+        # TODO: most appropriate error?
+        return PE_ERROR;
+    }
+    $exp->send($pwd . "\n");
+    my @r4 = $exp->expect(5, "Password changed", "Password change rejected: ");
+    unless( $r4[0] == 1 ){
+        $exp->hard_close();
+        $self->logger->error("kpasswd password change failed for " . $req->{user} . ": " . join(' | ', @r4[0,2-4]) );
+        if( $r4[4] =~ m{New password was used previously. Please choose a different password} ){
+            return PE_PP_PASSWORD_IN_HISTORY;
+        } else {
+            return PE_ERROR;
+        }
+    }
+
+    $exp->soft_close();
+    $self->logger->info("kpassword successful password change for " . $req->{user});
+
+    # if we get this far we've changed the password successfully
+    return PE_PASSWORD_OK;
+}
+
+# Override the checkPasswordQuality function from Password::Base because it has
+# a brain-dead 'special characters' policy.
+sub checkPasswordQuality {
+    my ( $self, $password ) = @_;
+
+    # Min size
+    if ( $self->conf->{passwordPolicyMinSize}
+        and length($password) < $self->conf->{passwordPolicyMinSize} )
+    {
+        $self->logger->error("Password too short");
+        return PE_PP_PASSWORD_TOO_SHORT;
+    }
+
+    # Min lower
+    if ( $self->conf->{passwordPolicyMinLower} ) {
+        my $lower = 0;
+        $lower++ while ( $password =~ m/\p{lowercase}/g );
+        if ( $lower < $self->conf->{passwordPolicyMinLower} ) {
+            $self->logger->error("Password has not enough lower characters");
+            return PE_PP_INSUFFICIENT_PASSWORD_QUALITY;
+        }
+    }
+
+    # Min upper
+    if ( $self->conf->{passwordPolicyMinUpper} ) {
+        my $upper = 0;
+        $upper++ while ( $password =~ m/\p{uppercase}/g );
+        if ( $upper < $self->conf->{passwordPolicyMinUpper} ) {
+            $self->logger->error("Password has not enough upper characters");
+            return PE_PP_INSUFFICIENT_PASSWORD_QUALITY;
+        }
+    }
+
+    # Min digit
+    if ( $self->conf->{passwordPolicyMinDigit} ) {
+        my $digit = 0;
+        $digit++ while ( $password =~ m/\d/g );
+        if ( $digit < $self->conf->{passwordPolicyMinDigit} ) {
+            $self->logger->error("Password has not enough digit characters");
+            return PE_PP_INSUFFICIENT_PASSWORD_QUALITY;
+        }
+    }
+
+    ## Special characters policy
+    my $speChars = $self->conf->{passwordPolicySpecialChar};
+    $speChars =~ s/\s+//g;
+
+    # Min special characters
+    if ( $self->conf->{passwordPolicyMinSpeChar} && $speChars ) {
+        my $spe  = 0;
+        my $test = $password;
+        $spe = $test =~ s/[\Q$speChars\E]//g;
+        if ( $spe < $self->conf->{passwordPolicyMinSpeChar} ) {
+            $self->logger->error("Password has not enough special characters");
+            return PE_PP_INSUFFICIENT_PASSWORD_QUALITY;
+        }
+    }
+
+#    # Fobidden special characters
+#    $password =~ s/[\Q$speChars\E\w]//g;
+#    if ($password) {
+#        $self->logger->error( 'Password contains '
+#              . length($password)
+#              . " forbidden character(s): $password" );
+#        return
+#          length($password) > 1
+#          ? PE_PP_NOT_ALLOWED_CHARACTERS
+#          : PE_PP_NOT_ALLOWED_CHARACTER;
+#    }
+
+    return PE_OK;
+}