Drizzled Public API Documentation

auth_pam.cc
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2009 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 /*
00021   Sections of this were taken/modified from mod_auth_path for Apache
00022   @TODO: License?
00023 */
00024 
00025 #include <config.h>
00026 
00027 #include <security/pam_appl.h>
00028 #if !defined(__sun) && !defined(__FreeBSD__)
00029 #include <security/pam_misc.h>
00030 #endif
00031 
00032 #include <drizzled/identifier.h>
00033 #include <drizzled/plugin/authentication.h>
00034 
00035 using namespace drizzled;
00036 
00037 typedef struct {
00038     const char *name;
00039     const char *password;
00040 } auth_pam_userinfo;
00041 
00042 extern "C"
00043 int auth_pam_talker(int num_msg,
00044 #ifdef __sun
00045                     struct pam_message **msg,
00046 #else
00047                     const struct pam_message **msg,
00048 #endif
00049                     struct pam_response **resp,
00050                     void *appdata_ptr);
00051 
00052 int auth_pam_talker(int num_msg,
00053 #ifdef __sun
00054                     struct pam_message **msg,
00055 #else
00056                     const struct pam_message **msg,
00057 #endif
00058                     struct pam_response **resp,
00059                     void *appdata_ptr)
00060 {
00061   auth_pam_userinfo *userinfo = (auth_pam_userinfo*)appdata_ptr;
00062   struct pam_response *response = 0;
00063 
00064   /* parameter sanity checking */
00065   if(not resp || not msg || not userinfo)
00066     return PAM_CONV_ERR;
00067 
00068   /* allocate memory to store response */
00069   response= (struct pam_response*)malloc(num_msg * sizeof(struct pam_response));
00070   if(!response)
00071     return PAM_CONV_ERR;
00072 
00073   /* copy values */
00074   for(int x= 0; x < num_msg; x++)
00075   {
00076     /* initialize to safe values */
00077     response[x].resp_retcode= 0;
00078     response[x].resp= 0;
00079 
00080     /* select response based on requested output style */
00081     switch(msg[x]->msg_style)
00082     {
00083     case PAM_PROMPT_ECHO_ON:
00084       /* on memory allocation failure, auth fails */
00085       response[x].resp = strdup(userinfo->name);
00086       break;
00087     case PAM_PROMPT_ECHO_OFF:
00088       response[x].resp = strdup(userinfo->password);
00089       break;
00090     default:
00091       if(response)
00092         free(response);
00093       return PAM_CONV_ERR;
00094     }
00095   }
00096 
00097   /* everything okay, set PAM response values */
00098   *resp = response;
00099 
00100   return PAM_SUCCESS;
00101 }
00102 
00103 class Auth_pam : public drizzled::plugin::Authentication
00104 {
00105 public:
00106   Auth_pam(std::string name_arg)
00107     : drizzled::plugin::Authentication(name_arg) {}
00108   virtual bool authenticate(const identifier::User &sctx,
00109                             const std::string &password)
00110   {
00111     int retval;
00112     auth_pam_userinfo userinfo= { NULL, NULL };
00113     struct pam_conv conv_info= { &auth_pam_talker, (void*)&userinfo };
00114     pam_handle_t *pamh= NULL;
00115 
00116     userinfo.name= sctx.username().c_str();
00117     userinfo.password= password.c_str();
00118 
00119     retval= pam_start("drizzle", userinfo.name, &conv_info, &pamh);
00120 
00121     if (retval == PAM_SUCCESS)
00122       retval= pam_authenticate(pamh, PAM_DISALLOW_NULL_AUTHTOK);
00123 
00124     if (retval == PAM_SUCCESS)
00125       retval= pam_acct_mgmt(pamh, PAM_DISALLOW_NULL_AUTHTOK);
00126 
00127     pam_end(pamh, retval);
00128 
00129     return (retval == PAM_SUCCESS) ? true: false;
00130   }
00131 };
00132 
00133 
00134 static Auth_pam *auth= NULL;
00135 
00136 static int initialize(drizzled::module::Context &context)
00137 {
00138   auth= new Auth_pam("auth_pam");
00139   context.add(auth);
00140   return 0;
00141 }
00142 
00143 DRIZZLE_DECLARE_PLUGIN
00144 {
00145   DRIZZLE_VERSION_ID,
00146   "pam",
00147   "0.1",
00148   "Brian Aker",
00149   "PAM based authenication.",
00150   PLUGIN_LICENSE_GPL,
00151   initialize, /* Plugin Init */
00152   NULL,   /* depends */
00153   NULL    /* config options */
00154 }
00155 DRIZZLE_DECLARE_PLUGIN_END;