summaryrefslogtreecommitdiff
path: root/security/cyrus-sasl2/files/pwcheck_pam.c
blob: 57e1076ca92a5743ae86ac87043be67ea45aba29 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include <security/pam_appl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/* Static variables used to communicate between the conversation function
 * and the server_login function
 */
static char *PAM_username;
static char *PAM_password;

/* PAM conversation function
 */
static int PAM_conv (int num_msg,
                     const struct pam_message **msg,
                     struct pam_response **resp,
                     void *appdata_ptr) {
  int replies = 0;
  struct pam_response *reply = NULL;

  #define COPY_STRING(s) (s) ? strdup(s) : NULL

  reply = malloc(sizeof(struct pam_response) * num_msg);
  if (!reply) return PAM_CONV_ERR;

  for (replies = 0; replies < num_msg; replies++) {
    switch (msg[replies]->msg_style) {
      case PAM_PROMPT_ECHO_ON:
        reply[replies].resp_retcode = PAM_SUCCESS;
        reply[replies].resp = COPY_STRING(PAM_username);
          /* PAM frees resp */
        break;
      case PAM_PROMPT_ECHO_OFF:
        reply[replies].resp_retcode = PAM_SUCCESS;
        reply[replies].resp = COPY_STRING(PAM_password);
          /* PAM frees resp */
        break;
      case PAM_TEXT_INFO:
        /* fall through */
      case PAM_ERROR_MSG:
        /* ignore it, but pam still wants a NULL response... */
        reply[replies].resp_retcode = PAM_SUCCESS;
        reply[replies].resp = NULL;
        break;
      default:
        /* Must be an error of some sort... */
        free (reply);
        return PAM_CONV_ERR;
    }
  }
  *resp = reply;
  return PAM_SUCCESS;
}

static struct pam_conv PAM_conversation = {
    PAM_conv,
    NULL
};

/* Server log in
 * Accepts: user name string
 *          password string
 * Returns: "OK" if password validated, error message otherwise
 */ 
 
char *pwcheck(char *username, char *password)
{
  pam_handle_t *pamh;
  int pam_error;

  /* PAM only handles authentication, not user information. */
  if ( !(username && password && strlen(username) && strlen(password)) )
      return "Incorrect username";

  /* validate password */

  PAM_password = password;
  PAM_username = username;
  fprintf(stderr, "checking %s\n", username);
  pam_error = pam_start("cyrus", username, &PAM_conversation, &pamh);
  if (pam_error == PAM_SUCCESS) 
    pam_error = pam_authenticate(pamh, 0);
    
  if (pam_error == PAM_SUCCESS) 
    pam_error = pam_acct_mgmt(pamh, 0);

  if ( pam_error == PAM_SUCCESS) 
    fprintf(stderr, "\tauthenticated %s\n", username);
  else
    fprintf(stderr, "\tfailed to authenticate %s\n", username);
  
  if(pam_end(pamh, pam_error) != PAM_SUCCESS) {
    pamh = NULL;
    fprintf(stderr, "pwcheck: failed to release authenticator\n");
    exit(1);
  }
  return ( pam_error == PAM_SUCCESS ? "OK" : "Incorrect passwd" );
}