Added SamOEMChangePassword functionality.
authorJeremy Allison <jra@samba.org>
Wed, 18 Mar 1998 19:07:53 +0000 (19:07 +0000)
committerJeremy Allison <jra@samba.org>
Wed, 18 Mar 1998 19:07:53 +0000 (19:07 +0000)
Jeremy.
(This used to be commit e02e3bcbbd4333113dde7bef47763fb229148007)

source3/include/proto.h
source3/libsmb/smbdes.c
source3/smbd/chgpasswd.c
source3/smbd/ipc.c

index 54f833a93e8886ae4d9789c16db9ae60e21a0dc6..e980bcacc9a517e3d6c2e892b93b2253b8ddcee8 100644 (file)
@@ -38,6 +38,10 @@ BOOL chgpasswd(char *name,char *oldpass,char *newpass);
 BOOL check_lanman_password(char *user, unsigned char *pass1, 
                            unsigned char *pass2, struct smb_passwd **psmbpw);
 BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsigned char *pass2);
+BOOL check_oem_password(char *user, unsigned char *data,
+                        struct smb_passwd **psmbpw, char *new_passwd,
+                        int new_passwd_size);
+BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd);
 
 /*The following definitions come from  client.c  */
 
@@ -1664,6 +1668,7 @@ void E_P24(unsigned char *p21, unsigned char *c8, unsigned char *p24);
 void D_P16(unsigned char *p14, unsigned char *in, unsigned char *out);
 void cred_hash1(unsigned char *out,unsigned char *in,unsigned char *key);
 void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key);
+void SamOEMhash( unsigned char *data, unsigned char *key);
 
 /*The following definitions come from  smbencrypt.c  */
 
index c345d051bd8af24c12b2a3cf22c2d95813fca2fe..8f95a5a297b51593c43317b8cd1c5a03447bbc8b 100644 (file)
@@ -341,3 +341,43 @@ void cred_hash2(unsigned char *out,unsigned char *in,unsigned char *key)
        smbhash(out, buf, key2, 1);
 }
 
+void SamOEMhash( unsigned char *data, unsigned char *key)
+{
+  unsigned char s_box[256];
+  unsigned char index_i = 0;
+  unsigned char index_j = 0;
+  unsigned char j = 0;
+  int ind;
+
+  for (ind = 0; ind < 256; ind++)
+  {
+    s_box[ind] = (unsigned char)ind;
+  }
+
+  for( ind = 0; ind < 256; ind++)
+  {
+     unsigned char tc;
+
+     j += (s_box[ind] + key[ind%16]);
+
+     tc = s_box[ind];
+     s_box[ind] = s_box[j];
+     s_box[j] = tc;
+  }
+
+  for( ind = 0; ind < 516; ind++)
+  {
+    unsigned char tc;
+    unsigned char t;
+
+    index_i++;
+    index_j += s_box[index_i];
+
+    tc = s_box[index_i];
+    s_box[index_i] = s_box[index_j];
+    s_box[index_j] = tc;
+
+    t = s_box[index_i] + s_box[index_j];
+    data[ind] = data[ind] ^ s_box[t];
+  }
+}
index c83ff1911c794c7606b63969a40888a73237501d..57d81ad756dd5ca3743a6e2900c6cb4127ed15ee 100644 (file)
@@ -493,3 +493,117 @@ BOOL change_lanman_password(struct smb_passwd *smbpw, unsigned char *pass1, unsi
     
   return ret;
 }
+
+/***********************************************************
+ Code to check the OEM hashed password.
+************************************************************/
+
+BOOL check_oem_password(char *user, unsigned char *data,
+                        struct smb_passwd **psmbpw, char *new_passwd,
+                        int new_passwd_size)
+{
+  struct smb_passwd *smbpw = NULL;
+  int new_pw_len;
+  fstring upper_case_new_passwd;
+  unsigned char new_p16[16];
+  unsigned char unenc_old_pw[16];
+
+  become_root(0);
+  *psmbpw = smbpw = get_smbpwd_entry(user, 0);
+  unbecome_root(0);
+
+  if(smbpw == NULL)
+  {
+    DEBUG(0,("check_oem_password: get_smbpwd_entry returned NULL\n"));
+    return False;
+  }
+
+  if(smbpw->acct_ctrl & ACB_DISABLED)
+  {
+    DEBUG(0,("check_lanman_password: account %s disabled.\n", user));
+    return False;
+  }
+
+  if(smbpw->smb_passwd == NULL)
+  {
+    DEBUG(0,("check_oem_password: no lanman password !\n"));
+    return False;
+  }
+
+  /* 
+   * Call the hash function to get the new password.
+   */
+  SamOEMhash( (unsigned char *)data, (unsigned char *)smbpw->smb_passwd);
+
+  /* 
+   * The length of the new password is in the last 4 bytes of
+   * the data buffer.
+   */
+  new_pw_len = IVAL(data,512);
+  if(new_pw_len < 0 || new_pw_len > new_passwd_size - 1) {
+    DEBUG(0,("check_oem_password: incorrect password length.\n"));
+    return False;
+  }
+
+  memcpy(new_passwd, &data[512-new_pw_len], new_pw_len);
+  new_passwd[new_pw_len] = '\0';
+
+  /*
+   * To ensure we got the correct new password, hash it and
+   * use it as a key to test the passed old password.
+   */
+
+  memset(upper_case_new_passwd, '\0', sizeof(upper_case_new_passwd));
+  fstrcpy(upper_case_new_passwd, new_passwd);
+  strupper(upper_case_new_passwd);
+
+  E_P16((uchar *)upper_case_new_passwd, new_p16);
+
+  /*
+   * Now use new_p16 as the key to see if the old
+   * password matches.
+   */
+  D_P16(new_p16, &data[516], unenc_old_pw);
+
+  if(memcmp(smbpw->smb_passwd, unenc_old_pw, 16)) {
+    DEBUG(0,("check_oem_password: old password doesn't match.\n"));
+    return False;
+  }
+
+  memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd));
+
+  return True;
+}
+
+/***********************************************************
+ Code to change the oem password. Changes both the lanman
+ and NT hashes.
+************************************************************/
+
+BOOL change_oem_password(struct smb_passwd *smbpw, char *new_passwd)
+{
+  int ret;
+  fstring upper_case_new_passwd;
+  unsigned char new_nt_p16[16];
+  unsigned char new_p16[16];
+
+  fstrcpy(upper_case_new_passwd, new_passwd);
+  strupper(upper_case_new_passwd);
+
+  E_P16((uchar *)upper_case_new_passwd, new_p16);
+
+  smbpw->smb_passwd = new_p16;
+  
+  E_md4hash((uchar *) new_passwd, new_nt_p16);
+  smbpw->smb_nt_passwd = new_nt_p16;
+  
+  /* Now write it into the file. */
+  become_root(0);
+  ret = mod_smbpwd_entry(smbpw);
+  unbecome_root(0);
+
+  memset(upper_case_new_passwd, '\0', strlen(upper_case_new_passwd));
+  memset(new_passwd, '\0', strlen(new_passwd));
+
+  return ret;
+}
index bbeeb21e963292b11822448c86465eb005cf2b95..89b3e36f52ffe25b8c8393ef92a5e3857ff1d9c8 100644 (file)
@@ -1662,6 +1662,65 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
   return(True);
 }
 
+/****************************************************************************
+  Set the user password (SamOEM version - gets plaintext).
+****************************************************************************/
+
+static BOOL api_SamOEMChangePassword(int cnum,uint16 vuid, char *param,char *data,
+                               int mdrcnt,int mprcnt,
+                               char **rdata,char **rparam,
+                               int *rdata_len,int *rparam_len)
+{
+  fstring user;
+  fstring new_passwd;
+  struct smb_passwd *smbpw = NULL;
+  char *p = param + 2;
+
+  *rparam_len = 2;
+  *rparam = REALLOC(*rparam,*rparam_len);
+
+  *rdata_len = 0;
+
+  SSVAL(*rparam,0,NERR_badpass);
+
+  /*
+   * Check the parameter definition is correct.
+   */
+  if(!strequal(param + 2, "zsT")) {
+    DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %sn\n", param + 2));
+    return False;
+  }
+  p = skip_string(p, 1);
+
+  if(!strequal(p, "B516B16")) {
+    DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %sn\n", p));
+    return False;
+  }
+  p = skip_string(p,1);
+
+  fstrcpy(user,p);
+  p = skip_string(p,1);
+
+  if(check_oem_password( user, data, &smbpw, new_passwd, sizeof(new_passwd)) == False) {
+    return True;
+  }
+
+  /* 
+   * At this point we have the new case-sensitive plaintext
+   * password in the fstring new_passwd. If we wanted to synchronise
+   * with UNIX passwords we would call a UNIX password changing 
+   * function here. However it would have to be done as root
+   * as the plaintext of the old users password is not 
+   * available. JRA.
+   */
+  if(change_oem_password( smbpw, new_passwd)) {
+    SSVAL(*rparam,0,NERR_Success);
+  }
+
+  return(True);
+}
+
 /****************************************************************************
   delete a print job
   Form: <W> <> 
@@ -3410,6 +3469,7 @@ struct
   {"WPrintDriverEnum", 205,    (BOOL (*)())api_WPrintDriverEnum,0},
   {"WPrintQProcEnum",  206,    (BOOL (*)())api_WPrintQProcEnum,0},
   {"WPrintPortEnum",   207,    (BOOL (*)())api_WPrintPortEnum,0},
+  {"SamOEMChangePassword", 214, (BOOL (*)())api_SamOEMChangePassword,0},
   {NULL,               -1,     (BOOL (*)())api_Unsupported,0}};