00001
00002
00003
00004
00005
00006
00007
00008 #include "wvlog.h"
00009 #include "wvpam.h"
00010 #include "wvautoconf.h"
00011
00012
00013 #ifndef HAVE_SECURITY_PAM_APPL_H
00014
00015 WvPam::WvPam(WvStringParm _appname)
00016 : log("PAM Auth", WvLog::Info), appname(_appname)
00017 {
00018 err.seterr("Compiled without PAM Support!\n");
00019 }
00020
00021
00022 WvPam::WvPam(WvStringParm _appname, WvStringParm rhost,
00023 WvStringParm user, WvStringParm password)
00024 : log("PAM Auth", WvLog::Info), appname(_appname)
00025 {
00026 err.seterr("Compiled without PAM Support!\n");
00027 }
00028
00029
00030 WvPam::~WvPam()
00031 {
00032 }
00033
00034 bool WvPam::authenticate(WvStringParm rhost, WvStringParm user, WvStringParm password)
00035 {
00036 return false;
00037 }
00038
00039 WvString WvPam::getuser() const
00040 {
00041 return WvString::null;
00042 }
00043
00044
00045 void WvPam::getgroups(WvStringList &l) const
00046 {
00047 }
00048
00049 #else // HAVE_SECURITY_PAM_APPL_H
00050
00051 #include <security/pam_appl.h>
00052 #include <sys/types.h>
00053 #include <pwd.h>
00054 #include <grp.h>
00055
00056 #include "wvaddr.h"
00057
00058
00059 class WvPamData
00060 {
00061 public:
00062 pam_handle_t *pamh;
00063 int status;
00064 WvString failmsg, user;
00065 WvStringList groups;
00066
00067 WvPamData()
00068 : pamh(NULL), status(PAM_SUCCESS), user("")
00069 { }
00070
00071 WvPamData(WvStringParm _failmsg)
00072 : pamh(NULL), status(PAM_SUCCESS), failmsg(_failmsg)
00073 { }
00074 };
00075
00076
00078 #if HAVE_BROKEN_PAM
00079 int noconv(int num_msg, struct pam_message **msgm,
00080 struct pam_response **response, void *userdata)
00081 #else
00082 int noconv(int num_msg, const struct pam_message **msgm,
00083 struct pam_response **response, void *userdata)
00084 #endif
00085 {
00086
00087 return PAM_CONV_ERR;
00088 }
00089
00090
00091
00092
00093
00094 #if HAVE_BROKEN_PAM
00095 static int passconv(int num_msg, struct pam_message **msgm,
00096 struct pam_response **response, void *userdata)
00097 #else
00098 static int passconv(int num_msg, const struct pam_message **msgm,
00099 struct pam_response **response, void *userdata)
00100 #endif
00101 {
00102 struct pam_response *password_echo;
00103
00104 password_echo = (struct pam_response *)calloc(num_msg,
00105 sizeof(struct pam_response));
00106 password_echo->resp = (char *)userdata;
00107 password_echo->resp_retcode = 0;
00108
00109 *response = password_echo;
00110
00111 return PAM_SUCCESS;
00112 }
00113
00114 WvPam::WvPam(WvStringParm _appname)
00115 : log("PAM Auth", WvLog::Info), appname(_appname)
00116 {
00117 init();
00118 }
00119
00120
00121 WvPam::WvPam(WvStringParm _appname, WvStringParm rhost,
00122 WvStringParm user, WvStringParm password)
00123 : log("PAM Auth", WvLog::Info), appname(_appname)
00124 {
00125 if (init())
00126 authenticate(rhost, user, password);
00127 }
00128
00129 WvPam::~WvPam()
00130 {
00131 log(WvLog::Debug2, "Shutting down PAM Session for: %s\n", appname);
00132 if (d->status == PAM_SUCCESS)
00133 pam_close_session(d->pamh, 0);
00134 pam_end(d->pamh, d->status);
00135 d->groups.zap();
00136 delete d;
00137 }
00138
00139
00140 bool WvPam::init()
00141 {
00142 d = new WvPamData();
00143 log(WvLog::Debug2, "Starting up PAM Session for: %s\n", appname);
00144 err.seterr("Not yet authenticated...");
00145
00146 struct pam_conv c;
00147 c.conv = noconv;
00148 c.appdata_ptr = NULL;
00149
00150 d->pamh = NULL;
00151 d->status = pam_start(appname, d->user, &c, &d->pamh);
00152 if (check_pam_status("pam_start")) return true;
00153 return false;
00154 }
00155
00156 bool WvPam::authenticate(WvStringParm rhost, WvStringParm user, WvStringParm password)
00157 {
00158
00159 assert(d);
00160
00161 if (!!rhost)
00162 {
00163 d->status = pam_set_item(d->pamh, PAM_RHOST, rhost);
00164 if (!check_pam_status("rhost setup"))
00165 return false;
00166 }
00167
00168 if (!!user)
00169 {
00170 d->user = user;
00171 d->status = pam_set_item(d->pamh, PAM_USER, user);
00172 if (!check_pam_status("user setup"))
00173 return false;
00174 }
00175
00176 if (!!password)
00177 {
00178 struct pam_conv c;
00179 c.conv = passconv;
00180 c.appdata_ptr = strdup(password);
00181 d->status = pam_set_item(d->pamh, PAM_CONV, &c);
00182 if (!check_pam_status("conversation setup"))
00183 return false;
00184
00185 d->status = pam_set_item(d->pamh, PAM_AUTHTOK, password);
00186 if (!check_pam_status("password setup"))
00187 return false;
00188 }
00189
00190 #if HAVE_BROKEN_PAM
00191 void *x = NULL;
00192 #else
00193 const void *x = NULL;
00194 #endif
00195 d->status = pam_get_item(d->pamh, PAM_USER, &x);
00196 if (!check_pam_status("get username"))
00197 return false;
00198 d->user = (const char *)x;
00199 d->user.unique();
00200
00201 log("Starting Authentication for %s@%s\n", d->user, rhost);
00202
00203 d->status = pam_authenticate(d->pamh, PAM_DISALLOW_NULL_AUTHTOK | PAM_SILENT);
00204 if (!check_pam_status("authentication")) return false;
00205
00206 d->status = pam_acct_mgmt(d->pamh, PAM_DISALLOW_NULL_AUTHTOK | PAM_SILENT);
00207 if (!check_pam_status("account management")) return false;
00208
00209 d->status = pam_setcred(d->pamh, PAM_ESTABLISH_CRED);
00210 if (!check_pam_status("credentials")) return false;
00211
00212 d->status = pam_open_session(d->pamh, 0);
00213 if (!check_pam_status("session open")) return false;
00214
00215
00216 if (!d->user)
00217 {
00218 #ifdef SOLARIS
00219 void *x = NULL;
00220 #else
00221 const void *x = NULL;
00222 #endif
00223 d->status = pam_get_item(d->pamh, PAM_USER, &x);
00224 if (!check_pam_status("get username")) return false;
00225 d->user = (const char *)x;
00226 d->user.unique();
00227 }
00228 log("Session open as user '%s'\n", d->user);
00229
00230
00231
00232 err.noerr();
00233
00234 return true;
00235 }
00236
00237
00238 bool WvPam::check_pam_status(WvStringParm s)
00239 {
00240 if (d->status == PAM_SUCCESS)
00241 {
00242 log(WvLog::Debug2, "PAM %s succeeded.\n", s);
00243 return true;
00244 }
00245 else
00246 {
00247 WvString msg("PAM %s failed: %s\n", s, pam_strerror(d->pamh, d->status));
00248 log(WvLog::Info, msg);
00249 err.seterr(msg);
00250 d->user = WvString::null;
00251 d->groups.zap();
00252 return false;
00253 }
00254 }
00255
00256
00257 WvString WvPam::getuser() const
00258 {
00259 return d->user;
00260 }
00261
00262
00263 void WvPam::getgroups(WvStringList &l) const
00264 {
00265 assert(l.isempty());
00266
00267
00268 if (d->groups.isempty())
00269 {
00270 setgrent();
00271 struct group *gr;
00272 while ((gr = getgrent()))
00273 {
00274 for (char **i = gr->gr_mem; *i != NULL; i++)
00275 {
00276 if (strcmp(*i, d->user) == 0)
00277 {
00278 d->groups.append(new WvString(gr->gr_name), true);
00279 break;
00280 }
00281 }
00282 }
00283 endgrent();
00284 }
00285
00286 WvStringList::Iter i(d->groups);
00287 for (i.rewind(); i.next(); )
00288 l.append(new WvString(*i), true);
00289 }
00290
00291
00292
00293
00294
00295
00296 #endif // HAVE_SECURITY_PAM_APPL_H