#define _XOPEN_SOURCE

#include <configure.h>

#include <stdio.h>
#include <pwd.h>
#include <ctype.h>
#include <errno.h>
#include <syslog.h>
#include <grp.h>
#include <stdlib.h>
#include <string.h>
#ifdef PAM_DEBUG
#include <syslog.h>
#endif

#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SHADOW_H
#include <shadow.h>
#endif

#include <general.h>

#ifndef HAVE_LIBPAM 
#undef PAM
#endif

#ifdef PAM

/* added PAM support Thomas Boll tb@boll.ch 9/2000
 * tested with LINUX-PAM
 */

extern "C" {
#include <security/pam_appl.h>
}

int pam_conv_func (int num_msg, const struct pam_message **msg,
                   struct pam_response **resp, void *appdata_ptr) {
 
    int i;
 
    /* allocate space for response array
     * this is the same length as the prompt
     * array (linux-pam > 0.59 or SUN).
     */
    *resp = (struct pam_response *)calloc (num_msg, 
                                        sizeof (struct pam_response));
    if (*resp == NULL) {  // out of memory 
        return PAM_CONV_ERR; 
    }
 
    for (i=0; i < num_msg; i++) {
 
        if ((msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) ||
            (msg[i]->msg_style == PAM_PROMPT_ECHO_ON)) {
 
            resp[i]->resp = (char *)malloc (strlen((char *)appdata_ptr)+1);
            strcpy (resp[i]->resp, (char *)appdata_ptr);
        }
    }                                                      
    return PAM_SUCCESS;
}
 
bool check_unix_passwd (const char *username, const char *passwd,
                        uid_t &uid, const char *program) {

    int ret;
    pam_handle_t *pah;
    int pam_status = PAM_SUCCESS;     

#ifdef PAM_DEBUG
    openlog("dkimap4", LOG_PID, LOG_MAIL);
    syslog(LOG_INFO, "DKIMAP authentication attempt: user=%s passwd=%s uid=%d program=%s", username, passwd, uid, program);
#endif

    static struct pam_conv pac = {
        pam_conv_func,
        (void *)passwd
    };                                                               

    ret = pam_start (program, username, &pac, &pah);
    if (ret != PAM_SUCCESS) return TRUE;
 
    ret = pam_authenticate(pah, PAM_SILENT);
    if (ret != PAM_SUCCESS) {
         (void)pam_end (pah, pam_status);
         return TRUE;
    }
 
    ret = pam_acct_mgmt(pah, PAM_SILENT);
    if (ret != PAM_SUCCESS) {
         (void)pam_end (pah, pam_status);
         return TRUE;
    }
 
    (void)pam_end (pah, pam_status);
    return FALSE;
}

#else /* no PAM */

bool check_unix_passwd(const char *username, const char *passwd,
                       uid_t &uid, const char *program)
 {
  struct passwd *pwd;
  char *encpw;
  char *encrypted_pass;

  #ifdef HAVE_SHADOW_H
  struct spwd *spwd;
  #endif

  /* Get encrypted password from password file */
  if((pwd=getpwnam(username))==NULL) return TRUE;

  uid=pwd->pw_uid;

  encrypted_pass=pwd->pw_passwd;

  #ifdef HAVE_SHADOW_H
  if(strcmp(pwd->pw_passwd, "x")==0 ||
     strcmp(pwd->pw_passwd, "*")==0 ||
     strcmp(pwd->pw_passwd, "*NP*")==0)
   {
    if((spwd=getspnam(username))==NULL)
      return TRUE;

    encrypted_pass = spwd->sp_pwdp;
   }
  #endif

  /* Run encryption algorythm */
  encpw=crypt(passwd, encrypted_pass);

  /* Check it */
  if(strcmp(encpw, encrypted_pass))
    return TRUE;

  return FALSE;
 }

#endif /* no PAM */


syntax highlighted by Code2HTML, v. 0.9.1