From dc47d56f62e6954e400856755aa5c67112812602 Mon Sep 17 00:00:00 2001
From: Jack Magne <jmagne@localhost.localdomain>
Date: Tue, 11 Aug 2015 18:26:04 -0700
Subject: [PATCH] setpin utility doesn't set the pin for users.

There were some things wrong with the setpin utility.

1. There were some syntax violations that had to be dealt with or a DS with syntax checking
would not be pleased.

2. The back end is expecting a byte of hash data at the beginning of the pin.
In our case we are sending NO hash so we want this code at the beginning '-'

3. We also need to prepend the dn in front of the pin so the back end can verify the set pin.

Tested to work during both steps of the setpin process: 1) Creating the schema, 2) creating the pin.
Tested to work with actual PinBased Enrollment.

4. Fix also now supports the SHA256 hashing method only, with the sha256 being the default hash.
The no hash option is supported but puts the pin in the clear.
---
 base/native-tools/src/setpin/setpin.c              | 57 ++++++++++------------
 base/native-tools/src/setpin/setpin_options.c      |  7 ++-
 .../authentication/UidPwdPinDirAuthentication.java |  5 ++
 3 files changed, 35 insertions(+), 34 deletions(-)

diff --git a/base/native-tools/src/setpin/setpin.c b/base/native-tools/src/setpin/setpin.c
index f1bf6a8..a164719 100644
--- a/base/native-tools/src/setpin/setpin.c
+++ b/base/native-tools/src/setpin/setpin.c
@@ -87,7 +87,7 @@ void testpingen();
 void do_setup();
 
 
-char *sha1_pw_enc( char *pwd );
+char *sha256_pw_enc( char *pwd );
 
 int errcode=0;
 
@@ -375,7 +375,7 @@ void do_setup() {
     doLDAPBind();
     
     if (o_schemachange) {   
-        sprintf(x_values[0],"( %s-oid NAME '%s' DESC 'User Defined Attribute' SYNTAX '1.3.6.1.4.1.1466.115.121.1.5' SINGLE-VALUE )",
+        sprintf(x_values[0],"( %s-oid NAME '%s' DESC 'User Defined Attribute' SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE X-ORIGIN 'custom for setpin' )",
             o_attribute,
             o_attribute);
 
@@ -398,8 +398,8 @@ void do_setup() {
             }
         }
 
-        sprintf(x_values[0],"( %s-oid NAME '%s' DESC 'User Defined ObjectClass' SUP 'top' MUST ( objectclass ) MAY ( aci $ %s )",
-           o_objectclass,o_objectclass,
+        sprintf(x_values[0],"( 2.16.840.1.117370.999.1.2.10 NAME '%s' DESC 'User Defined ObjectClass' SUP top MAY ( aci $ %s ) )",
+           o_objectclass,
            o_attribute);
 
         fprintf(stderr,"Adding objectclass: %s\n",x_values[0]);
@@ -433,7 +433,7 @@ void do_setup() {
             exitError("missing basedn argument");
         }
             
-        password = sha1_pw_enc( o_pinmanagerpwd );
+        password = sha256_pw_enc( o_pinmanagerpwd );
         
         fprintf(stderr,"Adding user: %s\n",o_pinmanager);
 
@@ -533,23 +533,23 @@ int ldif_base64_encode(
 /*
  * Number of bytes each hash algorithm produces
  */
-#define SHA1_LENGTH     20
-
+#define SHA256_LENGTH   32
 
 char *
-sha1_pw_enc( char *pwd )
+sha256_pw_enc( char *pwd )
 {
-    unsigned char   hash[ SHA1_LENGTH ];
+
+    unsigned char   hash[ SHA256_LENGTH ];
     char        *enc;
 
-    /* SHA1 hash the user's key */
-    PK11_HashBuf(SEC_OID_SHA1,hash,pwd,strlen(pwd));
+    /* SHA246 hash the user's key */
+    PK11_HashBuf(SEC_OID_SHA256,hash,pwd,strlen(pwd));
     enc = malloc(256);
 
-    sprintf( enc, "{SHA}");
+    sprintf( enc, "{SHA256}");
 
     (void)ldif_base64_encode( hash, enc + 5,
-        SHA1_LENGTH, -1 );
+        SHA256_LENGTH, -1 );
 
     return( enc );
 }
@@ -871,24 +871,17 @@ void processSearchResults(LDAPMessage *r) {
 
 #define SENTINEL_SHA1 0
 #define SENTINEL_MD5  1
+#define SENTINEL_SHA256 2
 #define SENTINEL_NONE '-' 
 
-            if ((!strcmp(o_hash,"SHA1")) || (!strcmp(o_hash,"sha1")) ) {
-                status = PK11_HashBuf(SEC_OID_SHA1,
-                                  (unsigned char *)hashbuf_dest+1,
-                                  (unsigned char *)hashbuf_source,
-                                  strlen(hashbuf_source)
-                                  );
-                hashbuf_dest[0] = SENTINEL_SHA1;
-                pindatasize = SHA1_LENGTH + 1;
-            } else if ((!strcmp(o_hash,"MD5")) || (!strcmp(o_hash,"md5")) ) {
-                status = PK11_HashBuf(SEC_OID_MD5,
+            if ((!strcmp(o_hash,"SHA256")) || (!strcmp(o_hash,"sha256")) ) {
+                status = PK11_HashBuf(SEC_OID_SHA256,
                                   (unsigned char *)hashbuf_dest+1,
                                   (unsigned char *)hashbuf_source,
                                   strlen(hashbuf_source)
                                   );
-                hashbuf_dest[0] = SENTINEL_MD5;
-                pindatasize = MD5_LENGTH + 1;
+                hashbuf_dest[0] = SENTINEL_SHA256;
+                pindatasize = SHA256_LENGTH + 1;
             } else if ((!strcmp(o_hash,"NONE")) || (!strcmp(o_hash,"none")) ) {
                 hashbuf_dest[0] = SENTINEL_NONE;
                 status = SECSuccess;
@@ -897,7 +890,7 @@ void processSearchResults(LDAPMessage *r) {
                        strlen(hashbuf_source)
                       );
             } else {
-                sprintf(errbuf,"Unsupported hash type '%s'. Must be one of 'sha1', 'md5' or 'none",o_hash);
+                sprintf(errbuf,"Unsupported hash type '%s'. Must be one of 'sha256', or 'none",o_hash);
                 errcode = 7;
                 exitError(errbuf);
             }
@@ -907,16 +900,20 @@ void processSearchResults(LDAPMessage *r) {
                 errcode = 9;
                 exitError(errbuf);
             }
-      
-            pindata = hashbuf_dest;
+      pindata = hashbuf_dest;
 
             if (hashbuf_source != NULL) {
                 free(hashbuf_source);
                 hashbuf_source = NULL;
             }
         } else {
-            pindata = generatedPassword;
-            pindatasize = strlen(generatedPassword);
+            /* Do last resort no hash version */
+            hashbuf_dest[0] = SENTINEL_NONE;
+            memcpy(hashbuf_dest + 1, dn, strlen(dn));
+            memcpy(hashbuf_dest + 1 + strlen(dn) ,generatedPassword, strlen(generatedPassword));
+
+            pindata = hashbuf_dest;
+            pindatasize = strlen(generatedPassword) + 1 + strlen(dn);
         }
     
         bval.bv_len = pindatasize;
diff --git a/base/native-tools/src/setpin/setpin_options.c b/base/native-tools/src/setpin/setpin_options.c
index d8ee83a..d2fb54d 100644
--- a/base/native-tools/src/setpin/setpin_options.c
+++ b/base/native-tools/src/setpin/setpin_options.c
@@ -51,7 +51,7 @@ char *valid_args[] = {
   "case",     "Restrict case of pins 'case=upperonly'",
   "objectclass", "Objectclass of LDAP entry to operate on    (default pinPerson)",
   "attribute","Which LDAP attribute to write to           (default pin)",
-  "hash",     "Hash algorithm used to store pin: 'none', 'md5' or 'sha1' (default)",
+  "hash",     "Hash algorithm used to store pin: 'none',  or 'sha256' (default) warning: 'none' is in the clear",
   "saltattribute", "Which attribute to use for salt            (default: dn)",
   "input",    "File to use for restricting DN's, or providing your own pins",
   "output",   "Redirect stdout to a file",
@@ -96,7 +96,7 @@ void setDefaultOptions() {
  o_gen=      "RNG-alphanum";
  o_case=     NULL;
  o_attribute="pin";
- o_hash=     "sha1";
+ o_hash=     "sha256";
  o_objectclass="pinPerson";
  o_output=   NULL;
  o_retry=    "5";
@@ -270,8 +270,7 @@ void validateOptions() {
   }
 
   if (!
-      (equals(o_hash,"sha1") ||
-       equals(o_hash,"md5") ||
+      (equals(o_hash,"sha256") ||
        equals(o_hash,"none"))
       ) {
     snprintf(errbuf, ERR_BUF_LENGTH, "invalid hash: %s",o_hash);
diff --git a/base/server/cms/src/com/netscape/cms/authentication/UidPwdPinDirAuthentication.java b/base/server/cms/src/com/netscape/cms/authentication/UidPwdPinDirAuthentication.java
index 82331da..6caa9a1 100644
--- a/base/server/cms/src/com/netscape/cms/authentication/UidPwdPinDirAuthentication.java
+++ b/base/server/cms/src/com/netscape/cms/authentication/UidPwdPinDirAuthentication.java
@@ -75,6 +75,7 @@ public class UidPwdPinDirAuthentication extends DirBasedAuthentication
 
     protected static final byte SENTINEL_SHA = 0;
     protected static final byte SENTINEL_MD5 = 1;
+    protected static final byte SENTINEL_SHA256 = 2;
     protected static final byte SENTINEL_NONE = 0x2d;
 
     /* Holds configuration parameters accepted by this implementation.
@@ -132,6 +133,7 @@ public class UidPwdPinDirAuthentication extends DirBasedAuthentication
     protected String mPinAttr = DEF_PIN_ATTR;
     protected MessageDigest mSHADigest = null;
     protected MessageDigest mMD5Digest = null;
+    protected MessageDigest mSHA256Digest = null;
 
     private ILdapConnFactory removePinLdapFactory = null;
     private LDAPConnection removePinLdapConnection = null;
@@ -165,6 +167,7 @@ public class UidPwdPinDirAuthentication extends DirBasedAuthentication
         try {
             mSHADigest = MessageDigest.getInstance("SHA1");
             mMD5Digest = MessageDigest.getInstance("MD5");
+            mSHA256Digest = MessageDigest.getInstance("SHA256");
         } catch (NoSuchAlgorithmException e) {
             throw new EAuthException(CMS.getUserMessage("CMS_AUTHENTICATION_INTERNAL_ERROR", e.getMessage()));
         }
@@ -336,6 +339,8 @@ public class UidPwdPinDirAuthentication extends DirBasedAuthentication
             pinDigest = mSHADigest.digest(toBeDigested.getBytes());
         } else if (hashtype == SENTINEL_MD5) {
             pinDigest = mMD5Digest.digest(toBeDigested.getBytes());
+        } else if (hashtype == SENTINEL_SHA256) {
+            pinDigest = mSHA256Digest.digest(toBeDigested.getBytes());
         } else if (hashtype == SENTINEL_NONE) {
             pinDigest = toBeDigested.getBytes();
         } else {
-- 
2.1.0

