char salt[3], crypted_password[CRYPTEDPWD_LEN+1];
char salt[12], crypted_password[CRYPTEDPWD_LEN+1];
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags,				   int argc, const char **argv) {   int retval, pcnt, pwdfilename_found;   const char *name;   char *password;   char pwdfilename[PWDFN_LEN];   char salt[3], crypted_password[CRYPTEDPWD_LEN+1];   FILE *pwdfile;   int use_flock = 0;   /* we require the pwdfile switch and argument to be present, else we don't work */   /* pcnt is the parameter counter variable for iterating through argv */   pcnt = pwdfilename_found = 0;   do {      /* see if the current parameter looks like "pwdfile" */      if (strcmp(argv[pcnt],PWDF_PARAM)==0) {	 /* if argv is long enough, grab the subsequent parameter */	 if (pcnt+1 < argc) {	    /* make sure we can't overflow */	    strncpy(pwdfilename,argv[++pcnt],PWDFN_LEN);	    /* indicate that we've found it */	    pwdfilename_found = 1;	 }	 /* also check for "pwdfile=blah" */      } else if (strncmp(argv[pcnt],PWDF_PARAM "=",sizeof(PWDF_PARAM "=")-1)==0) {	 /* make sure we can't overflow */	 strncpy(pwdfilename,argv[pcnt]+sizeof(PWDF_PARAM),PWDFN_LEN);	 /* indicate that we've found it */	 pwdfilename_found = 1;      } else if (strcmp(argv[pcnt],FLOCK_PARAM)==0) {	 /* we have a "flock" parameter */	 use_flock = 1;      } else if (strcmp(argv[pcnt],"no" FLOCK_PARAM)==0) {	 /* or a "noflock" parameter */	 use_flock = 0;      }   } while (++pcnt < argc);      /* for some or other reason, the password file wasn't specified */   if (!pwdfilename_found) {      _pam_log(LOG_ERR,"password file name not specified");      return PAM_AUTHINFO_UNAVAIL;   }      /* DEBUG */   D(_pam_log(LOG_ERR, "password filename extracted"));      /* now try to open the password file */   if ((pwdfile=fopen(pwdfilename,"r"))==NULL) {      _pam_log(LOG_ERR,"couldn't open password file %s",pwdfilename);      return PAM_AUTHINFO_UNAVAIL;   }      /* set a lock on the password file */   if (use_flock && lock_fd(fileno(pwdfile)) == -1) {      _pam_log(LOG_ERR,"couldn't lock password file %s",pwdfilename);      return PAM_AUTHINFO_UNAVAIL;   }      /* get user name */   if ((retval = pam_get_user(pamh,&name,"login: ")) != PAM_SUCCESS) {      _pam_log(LOG_ERR, "username not found");      fclose(pwdfile);      return retval;   }      /* DEBUG */   D(_pam_log(LOG_ERR,"username is %s", name));      /* get password - code from pam_unix_auth.c */   pam_get_item(pamh, PAM_AUTHTOK, (void *)&password);   if (!password) {      retval = _set_auth_tok(pamh, flags, argc, argv);      if (retval!=PAM_SUCCESS) {	 fclose(pwdfile);	 return retval;      }   }   pam_get_item(pamh, PAM_AUTHTOK, (void *)&password);      if ((retval = pam_get_item(pamh, PAM_AUTHTOK, (void *)&password)) != PAM_SUCCESS) {      _pam_log(LOG_ERR, "auth token not found");      fclose(pwdfile);      return retval;   }      /* DEBUG */   D(_pam_log(LOG_ERR,"got password from user", password));      /* now crypt password and compare to the user entry in the password file */   /* first make sure password is long enough -- may I do this? */   if (strlen(password)<2 || password==NULL) {      _pam_log(LOG_ERR,"password too short or NULL");      fclose(pwdfile);      return PAM_AUTH_ERR;   }      /* get the crypted password corresponding to this user */   if (!fgetpwnam(pwdfile, name, crypted_password)) {      _pam_log(LOG_ERR,"password file corrupt");      fclose(pwdfile);      return PAM_AUTHINFO_UNAVAIL;   }      /* DEBUG */   D(_pam_log(LOG_ERR,"got crypted password == %s", crypted_password));      /* extract the salt */   salt[0] = crypted_password[0]; salt[1] = crypted_password[1]; salt[2] = '\0';      /* DEBUG */   D(_pam_log(LOG_ERR,"user password crypted is %s", crypt(password,salt)));      /* if things don't match up, complain */   crypted_password[CRYPTEDPWD_LEN] = '\0';   if (strcmp(crypt(password,salt),crypted_password)!=0) {      _pam_log(LOG_ERR,"wrong password for user %s",name);      fclose(pwdfile);      return PAM_AUTH_ERR;   }      /* DEBUG */   D(_pam_log(LOG_ERR,"passwords match"));      /* we've gotten here, i.e. authentication was sucessful! */   fclose(pwdfile);   return PAM_SUCCESS;}