D3 and mvBase

Expand all | Collapse all

D3 Password Management

  • 1.  D3 Password Management

    ROCKETEER
    Posted 4 days ago
    A while back, D3 introduced the concept of Host Authentication to give users the ability to manage passwords and password standards using O/S authentication ( Active Directory, LDAP, whatever ). This is detailed in the D3 System Administration Guides:

    https://www3.rocketsoftware.com/rocketd3/support/documentation/d3nt/103/admin/index.htm
    https://www3.rocketsoftware.com/rocketd3/support/documentation/d3linux/103/admin/index.htm
    https://www3.rocketsoftware.com/rocketd3/support/documentation/AIX/103/admin/index.htm

    While that is a really good thing to implement and highly recommended by Rocket D3 staff, including myself, sometimes it can be a bit challenging to implement. For those of you who simply want a way to enforce D3 password standards ( expiry, history, length, character content ) from within D3 itself, you might want to take a look at this program I wrote for an end user. To implement it, you would call this program from the USERS file item logon macro ( somewhere after TERM-TYPE on A12 and before you LOGTO any account ) and create a file in DM ( or somewhere else with a Q-pointer thereto from DM ). Details in the program comments. Have a look, enjoy, and please post any comments, improvements or other points of view herein.

    * userpwd.pgm - bsc 09/29/21
    *
    * Manage password criteria:
    * Expiry
    * Length
    * Character content
    * History
    *
    * NOTE: D3 supports multiple user passwords in
    * A7 of the users item, support for that
    * not yet implemented in this program
    *
      prompt ''
      open 'users' to f.users else stop
    *
    * userpwd file must exist either in DM
    * or Q-pointed from DM, else program disabled
    *
      open 'userpwd' to f.pwd else stop
      read uitem from f.users,@user else stop
    *
    * If no current password, program disabled
    *
      pwcur = uitem<7,1>
      if len(pwcur) = 8 else stop
    *
    * Set up expiry days, password history count
    * and valid character constants
    *
      pwexp = 90
      pwcnt = 6
      nchar = "0123456789"
      uchar = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
      lchar = "abcdefghijklmnopqrstuvwxyz"
      schar = "!#$%_-"
    *
    * Read the userpwd item or initialize and make
    * sure the current password exists in history
    *
      read pitem from f.pwd,@user else
        pitem = uitem<7,1>
        pitem<2> = date()
      end
      locate pwcur in pitem<1> setting ix else
        pitem<pwcnt> = ""
        ins pwcur before pitem<1,1>
        del pitem<1,pwcnt+1>
      end
      write pitem on f.pwd,@user
    *
    * Set up expiry date and check to see if the
    * current password is expired or will soon,
    * prompt for new password in either case
    *
      dtexp = pitem<2> + pwexp
      begin case
        case dtexp <= date()
          crt "Password is expired"
          gosub EnterPwd
          if pwnew = "" then execute "off"
        case dtexp <= (date() + 15)
          crt "Password expires in ":(dtexp - date()):" day(s)"
          crt "Change Password (y)?":
          input yesno
          if yesno[1,1] = "y" then
            gosub EnterPwd
            if pwnew = "" then execute "off"
          end
      end case
    *
    stop
    *
    EnterPwd:
    *
    * If any failure to meet standards,
    * pwnew set to null telling main
    * program to fail and log user off
    *
      casing on
      crt "Enter new password: ":
      echo off
      input pwnew
      echo on
    *
      pwlen = len(pwnew)
      if pwlen < 8 then
        crt "Failed: shorter than 8 characters"
        pwnew = ""
      end else
        isnum = 0
        islow = 0
        isupr = 0
        isspc = 0
        for px = 1 to pwlen
          wch = pwnew[px,1]
          if index(nchar,wch,1) then isnum = 1
          if index(uchar,wch,1) then isupr = 1
          if index(lchar,wch,1) then islow = 1
          if index(schar,wch,1) then isspc = 1
        next px
      end
    *
      begin case
        case not(isnum)
          crt "Failed: no numeric characers (":nchar:")"
          pwnew = ""
        case not(isupr)
          crt "Failed: no upper-case characers (":uchar:")"
          pwnew = ""
        case not(islow)
          crt "Failed: no lower-case characers (":lchar:")"
          pwnew = ""
        case not(isspc)
          crt "Failed: no special characers (":schar:")"
          pwnew = ""
      end case
    *
    * Reenter password to make sure they match
    *
      if pwnew = "" else
        crt "Reenter new password: ":
        echo off
        input w
        echo on
        if w = pwnew else
          crt "Passwords do not match."
          pwnew = ""
        end
      end
    *
    * Make sure new password is not in recent usage list
    *
      if pwnew = "" else
        pwnew = iconv(pwnew,"u0c")
        locate pwnew in pitem<1> setting ix then
          crt "Failed: password recently used"
          pwnew = ""
        end else
    *
    * If everything good, update password history
    * file and write new password on users file
    *
          writev pwnew on f.users,@user,7
          ins pwnew before pitem<1,1>
          del pitem<1,pwcnt+1>
          pitem<2> = date()
          write pitem on f.pwd,@user
        end
      end
      casing off
    return
    *
    * End of source



    ------------------------------
    Brian S. Cram
    Principal Technical Support Engineer
    Rocket Software
    ------------------------------


  • 2.  RE: D3 Password Management

    Posted 3 days ago
    Morning Brian,

    Nice post!  sorry for the late reply but you know work gets in the way!

    I just wanted to mention that we decided to go somewhere in the middle as far as login and who controls the password.  We still create the user but use a subroutine to verify the password via LDAP and our AD server.  This way we still can limit access but use AD as the single password for all systems.   If anyone is interested I could scrub the program and share.

    Thanks Again for keeping us thinking.

    Craig

    ------------------------------
    Craig Curtis
    System Programmer
    Sevier Valley School District
    Richfield UT United States
    ------------------------------



  • 3.  RE: D3 Password Management

    ROCKETEER
    Posted 2 days ago
    Hey, Craig, I don't know about anyone else, but I'd LOVE to see that at your convenience! Thanks in advance.

    ------------------------------
    Brian S. Cram
    Principal Technical Support Engineer
    Rocket Software
    ------------------------------



  • 4.  RE: D3 Password Management

    Posted 2 days ago
    here is the pick basic code.  Don't laugh :)

    CNTR = 0

    EXECUTE "BREAK-KEY-OFF"
    EXECUTE "CLS"

    10 IF CNTR = 3 THEN EXECUTE "OFF"
    CRT "Case sensitive Password"
    CRT "SSD Password Please:":
    ECHO OFF
    INPUT PASSWORD.ORG
    IF PASSWORD.ORG = '' THEN CNTR += 1; GOTO 10
    ECHO ON
    WHO = ICONV(0, 'U50BB')
    INITIALS.ORG = FIELD(WHO, ' ', 3)

    DOME = "!php ldap.php ":INITIALS.ORG:" '":PASSWORD.ORG:"'"
    EXECUTE DOME CAPTURING OUT

    IF OUT<1> = "success" THEN
    * GOOD LDAP LOGIN
    CRT "GOOD LOGIN"
    END ELSE
    CNTR += 1
    CRT "BAD LOGIN, ATTEMPT ":CNTR
    GOTO 10
    END
    EXECUTE "BREAK-KEY-ON" CAPTURING OUT
    CRT "HIT YOUR CAPS LOCK"

    and you will need the php file ldap.php - this does the actual authentication.  Use this for both our web server authentication and for the D3 users.   Have sanitized with xx  

    <?php
    // this is in production. This provides authentication services for web.login and also d3 users login

    ini_set('display_errors', 0);
    error_reporting(0);

    $cnname = $argv[1];
    $password = $argv[2];

    $attributes_ad = array("displayName","description","cn");
    $tree = "DC=xx,DC=xx,DC=xx";

    $username = $cnname."@xx.xx.xx";
    $samaccountname = $cnname;

    //ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);

    $con = ldap_connect('ldaps://xx.xx.xx.xx:636' );
    ldap_set_option($con, LDAP_OPT_PROTOCOL_VERSION, 3);
    ldap_set_option($con, LDAP_OPT_REFERRALS, 0);
    ldap_set_option($con, LDAP_OPT_NETWORK_TIMEOUT, 1);
    ldap_set_option($con, LDAP_OPT_DIAGNOSTIC_MESSAGE, 0);

    if ($bind = ldap_bind($con, $username, $password)) {
    print "success\r\n";
    $result = ldap_search($con,$tree,"(sAMAccountName=$samaccountname)");
    $data = ldap_get_entries($con, $result);
    print_r( $data[0]['employeeid'][0]);
    print "\n\r"
    } else {
    print "failure\n\r";
    }

    ?>


    ------------------------------
    Craig Curtis
    System Programmer
    Sevier Valley School District
    Richfield UT United States
    ------------------------------