//Sample code file: var/ndk/webBuildengine/tmp/viewable_samples/a4ad0b48-dd95-46b6-8289-721e99c8dc76/login_method/lsm/common/src/cpwdlsm.c

//Warning: This code has been marked up for HTML

/*
**
Method Name:        Clear Password LSM
Method Platform:   Common

Copyright (C) 2002 Novell, Inc. All Rights Reserved. 

THIS WORK IS SUBJECT TO U.S. AND INTERNATIONAL COPYRIGHT LAWS AND
TREATIES. USE AND REDISTRIBUTION OF THIS WORK IS SUBJECT TO THE
LICENSE AGREEMENT ACCOMPANYING THE SOFTWARE DEVELOPMENT KIT
(SDK) THAT CONTAINS THIS WORK. PURSUANT TO THE SDK LICENSE
AGREEMENT, NOVELL HEREBY GRANTS TO DEVELOPER A ROYALTY-FREE,
NON-EXCLUSIVE LICENSE TO INCLUDE NOVELL'S SAMPLE CODE IN ITS
PRODUCT. NOVELL GRANTS DEVELOPER WORLDWIDE DISTRIBUTION RIGHTS TO
MARKET, DISTRIBUTE, OR SELL NOVELL'S SAMPLE CODE AS A COMPONENT OF
DEVELOPER'S PRODUCTS. NOVELL SHALL HAVE NO OBLIGATIONS TO
DEVELOPER OR DEVELOPER'S CUSTOMERS WITH RESPECT TO THIS CODE.
*/

class='cKeyword'>#if defined(N_PLAT_UNIX)     /* for logging in /var/adm/messages*/
class='cKeyword'>#if defined(LINUX)
        class='cKeyword'>#include <err.h>
class='cKeyword'>#endif
   class='cKeyword'>#include <ntypes.h>
   class='cKeyword'>#include <syslog.h>
class='cKeyword'>#endif

class='cKeyword'>#include <stdlib.h>
class='cKeyword'>#include <stdio.h>
class='cKeyword'>#include <unicode.h>
class='cKeyword'>#include <string.h>

class='cKeyword'>#include "nmaserr.h"
class='cKeyword'>#include "maf.h"
class='cKeyword'>#include "defines.h"

int SetThreadGroupID(int ourThreadGroupID);
class='cKeyword'>class='cKeyword'>#ifdef DEBUG
   class='cKeyword'>class='cKeyword'>#ifdef N_PLAT_UNIX
      class='cKeyword'>#define TRACE0(msg)         syslog(LOG_ERR, msg)
      class='cKeyword'>#define TRACE(msg)         syslog(LOG_ERR, msg)
      class='cKeyword'>#define TRACE1(msg, arg1)   syslog(LOG_ERR, msg, arg1)
   class='cKeyword'>#else // not unix
      class='cKeyword'>#define TRACE               printf
      class='cKeyword'>#define TRACE1               printf
      class='cKeyword'>#define TRACE2               printf
   class='cKeyword'>#endif
class='cKeyword'>#else // no debug
  class='cKeyword'>#define TRACE(msg) 
  class='cKeyword'>#define TRACE1(msg, arg1) 
  class='cKeyword'>#define TRACE2(msg, arg1, arg2) 
class='cKeyword'>#endif

extern int ourThreadGroupID;
extern int activeThreadCount;

/* ******************************************************************* */
// LOGIN Server METHOD (LSM)
/* ******************************************************************* */
int LSM00000001(MAF_Handle mh)
{
   int mafErr=0, err=0;
   unicode pwdTag[] = CLEAR_PWD_TAG;
   int thisThreadGroupID; 
   class='cKeyword'>char pwd[MAX_CLEAR_PWD_CHARS] = {0};
   size_t pwdLen = 0;
   class='cKeyword'>char storedPwd[MAX_CLEAR_PWD_CHARS] = {0};
   size_t storedPwdLen = 0;
   class='cKeyword'>char newPwd[MAX_CLEAR_PWD_CHARS] = {0};
   size_t newPwdLen = 0;
   size_t replyLen = 0;
   CPWD_INFO pwdInfo; 

   TRACE("CPWD LSM ENTER\n");

   // Mark LSM as in use
   activeThreadCount++;   
   thisThreadGroupID = SetThreadGroupID(ourThreadGroupID);

   // Request that NMAS start the LCM on the client side
   mafErr = MAF_Begin (mh);
   if (mafErr)
   {
      goto INIT_ERROR;
   }
   TRACE("CPWD LSM MAF_Begin OK\n");

   // Read password information from LCM
   mafErr = MAF_Read(mh, &replyLen, &pwdInfo);
   if (mafErr)
   {
      TRACE("CPWD MAF_Read pwdInfo FAILED]\n");
      goto MAF_ERROR;
   }
   if (replyLen < sizeof(pwdInfo))
   {
      mafErr = NMAS_E_LOGIN_FAILED;
      goto MAF_ERROR;
   }
   
   // Convert error to local byte order
   NCopyFromLoHi32(&err, &pwdInfo.error);
   
   // LCM failed so abort
   if (err)
   {
      goto MAF_ERROR;
   }
   
   // read password over MAF encrypted transport
   mafErr = MAF_XRead(mh, &pwdLen, pwd);
   if (mafErr)
   {
      TRACE("CPWD MAF_XRead password FAILED]\n");
      goto MAF_ERROR;
   }
   if (replyLen == 0)
   {
      mafErr = NMAS_E_LOGIN_FAILED;
      goto MAF_ERROR;
   }
   
   // get stored digest type and digest
   storedPwdLen = sizeof(storedPwd);
   err = MAF_GetAttribute(mh, NMAS_AID_USER_SECRET_DATA, pwdTag, &storedPwdLen, storedPwd);
   if (err)
   {
      TRACE1("CPWD MAF_GetAttribute (password) = %d", err);
      goto REPORT_ERROR;
   }

   // Verify password length is in range before calling strncmp()
   if (storedPwdLen != pwdLen)
   {
      err = NMAS_E_LOGIN_FAILED;
      TRACE1("CPWD Password length out of range (%d)", err);
      goto REPORT_ERROR;
   }

   // passwords are class='cKeyword'>case sensitive
   if(strncmp(storedPwd, pwd, storedPwdLen) != 0)
   {
      err = NMAS_E_LOGIN_FAILED;
      TRACE("CPWD password didn't match");
   }
   
   memset(storedPwd, 0xCC, sizeof(storedPwd)); // over-write password
   memset(pwd, 0xCC, sizeof(pwd)); // over-write password
   
   if (err)
   {
      goto REPORT_ERROR;
   }

   // write success to LCM
   mafErr = MAF_Write( mh, 4, &err );
   if (mafErr)
   {
      TRACE1("CPWD MAF_Write (success) FAILED Error %d\n", mafErr);
      goto MAF_ERROR;
   }

   //see if request for password change was made
   if ((pwdInfo.infoFlags & PASSWORD_CHANGE) != 0)
   {
      mafErr = MAF_XRead( mh, &newPwdLen, newPwd ); // read new password over MAF encrypted transport
      if (mafErr)
      {
         TRACE("CPWD MAF_XRead (new password) FAILED]\n");
         goto MAF_ERROR;
      }
      if (replyLen == 0)
      {
         mafErr = NMAS_E_LOGIN_FAILED;
         goto MAF_ERROR;
      }

      // set the new password
      err = MAF_PutAttribute( mh, NMAS_AID_USER_SECRET_DATA, pwdTag, strlen(newPwd)+1, newPwd);
      memset(newPwd, 0xCC, sizeof(newPwd)); // over-write password
      
      if (err)
      {
         TRACE1("CPWD Set Password = %d", err);
         goto REPORT_ERROR;
      }

      // write success to LCM
      mafErr = MAF_Write( mh, 4, &err );
      if (mafErr)
      {
         TRACE1("CPWD MAF_Write (Set Password success) FAILED Error %d\n", mafErr);
         goto MAF_ERROR;
      }
   }

REPORT_ERROR:

   // send success or failure to LCM
   if (err)
   {
      // write success or failure
      mafErr = MAF_Write( mh, 4, &err );
      {
         TRACE1("CPWD MAF_Write (failure) FAILED Error %d\n", mafErr);
      }
   }
   
MAF_ERROR:

   if (!err)
   {
      err = mafErr;
   }

   if (!err)
   {
      TRACE("Clear Password Login Successful.\n");
   }
   else 
   {
      TRACE("Clear Password Login Failed.\n");
   }

   MAF_End (mh, err, 0, 0);

INIT_ERROR:

   activeThreadCount--;   
   
   SetThreadGroupID(thisThreadGroupID);

   // return only fatal MAF errors
   return mafErr;
}