~drizzle-trunk/drizzle/development

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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/*
 -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
  Sections of this where taken/modified from mod_auth_path for Apache
*/

#include <drizzled/server_includes.h>
#include <drizzled/session.h>
#include <drizzled/plugin_authentication.h>
#include <security/pam_appl.h>
#ifndef __sun
#include <security/pam_misc.h>
#endif

typedef struct {
    const char *name;
    const char *password;
} auth_pam_userinfo;

static int auth_pam_talker(int num_msg,
#ifdef __sun
                           struct pam_message **msg,
#else
                           const struct pam_message **msg,
#endif
                           struct pam_response **resp,
                           void *appdata_ptr)
{
  auth_pam_userinfo *userinfo = (auth_pam_userinfo*)appdata_ptr;
  struct pam_response *response = 0;
  int x;

  /* parameter sanity checking */
  if(!resp || !msg || !userinfo)
    return PAM_CONV_ERR;

  /* allocate memory to store response */
  response= (struct pam_response*)malloc(num_msg * sizeof(struct pam_response));
  if(!response)
    return PAM_CONV_ERR;

  /* copy values */
  for(x= 0; x < num_msg; x++)
  {
    /* initialize to safe values */
    response[x].resp_retcode= 0;
    response[x].resp= 0;

    /* select response based on requested output style */
    switch(msg[x]->msg_style)
    {
    case PAM_PROMPT_ECHO_ON:
      /* on memory allocation failure, auth fails */
      response[x].resp = strdup(userinfo->name);
      break;
    case PAM_PROMPT_ECHO_OFF:
      response[x].resp = strdup(userinfo->password);
      break;
    default:
      if(response)
        free(response);
      return PAM_CONV_ERR;
    }
  }

  /* everything okay, set PAM response values */
  *resp = response;

  return PAM_SUCCESS;
}

static bool authenticate(Session *session, const char *password)
{
  int retval;
  auth_pam_userinfo userinfo= { NULL, NULL };
  struct pam_conv conv_info= { &auth_pam_talker, (void*)&userinfo };
  pam_handle_t *pamh= NULL;

  userinfo.name= session->security_ctx.user.c_str();
  userinfo.password= password;

  retval= pam_start("check_user", userinfo.name, &conv_info, &pamh);

  if (retval == PAM_SUCCESS)
    retval= pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK);

  if (retval == PAM_SUCCESS)
    retval= pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK);

  pam_end(pamh, retval);

  return (retval == PAM_SUCCESS) ? true: false;
}

static int initialize(void *p)
{
  authentication_st *auth= (authentication_st *)p;

  auth->authenticate= authenticate;

  return 0;
}

static int finalize(void *p)
{
  (void)p;

  return 0;
}

mysql_declare_plugin(auth_pam)
{
  DRIZZLE_AUTH_PLUGIN,
  "pam",
  "0.1",
  "Brian Aker",
  "PAM based authenication.",
  PLUGIN_LICENSE_GPL,
  initialize, /* Plugin Init */
  finalize, /* Plugin Deinit */
  NULL,   /* status variables */
  NULL,   /* system variables */
  NULL    /* config options */
}
mysql_declare_plugin_end;