00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "wvlog.h"
00013 #include "wvpam.h"
00014 #include "wvautoconf.h"
00015
00016
00017 #ifndef HAVE_SECURITY_PAM_APPL_H
00018
00019 WvPamStream::WvPamStream(WvStream *cloned, WvStringParm name, WvStringParm
00020 success, WvStringParm fail) :
00021 WvStreamClone(cloned)
00022 {
00023 WvLog log("WvPamStream", WvLog::Warning);
00024 log("Compiled without PAM support\n");
00025 if (cloned && !!fail)
00026 cloned->write(fail.cstr(), fail.len());
00027 }
00028
00029 WvPamStream::~WvPamStream()
00030 {
00031 }
00032
00033 bool WvPamStream::isok() const
00034 {
00035 return false;
00036 }
00037
00038 bool WvPamStream::check_pam_status(WvStringParm step)
00039 {
00040 return false;
00041 }
00042
00043 WvString WvPamStream::getuser() const
00044 {
00045 return WvString::null;
00046 }
00047
00048 void WvPamStream::getgroups(WvStringList &l) const
00049 {
00050 }
00051
00052 #else // HAVE_SECURITY_PAM_APPL_H
00053
00054 #include <security/pam_appl.h>
00055 #include <sys/types.h>
00056 #include <pwd.h>
00057 #include <grp.h>
00058
00059 #include "wvaddr.h"
00060
00061
00062 class WvPamData
00063 {
00064 public:
00065 pam_handle_t *pamh;
00066 int status;
00067 WvStringParm failmsg;
00068 WvString user;
00069 WvStringList groups;
00070
00071 WvPamData(WvStringParm _failmsg) :
00072 pamh(NULL), status(PAM_SUCCESS), failmsg(_failmsg)
00073 { }
00074 };
00075
00076
00077
00078 int noconv(int num_msg, const struct pam_message **msgm,
00079 struct pam_response **response, void *userdata)
00080 {
00081
00082 return PAM_CONV_ERR;
00083 }
00084
00085
00086
00087
00088
00089 WvPamStream::WvPamStream(WvStream *cloned, WvStringParm name,
00090 WvStringParm successmsg, WvStringParm failmsg) :
00091 WvStreamClone(cloned),
00092 d(new WvPamData(failmsg))
00093 {
00094
00095 struct pam_conv c;
00096 c.conv = noconv;
00097 c.appdata_ptr = NULL;
00098
00099
00100 struct passwd *pw = getpwuid(getuid());
00101 assert(pw);
00102 d->user = pw->pw_name;
00103
00104
00105 WvString rhost(*src());
00106
00107
00108 d->status = pam_start(name, d->user, &c, &d->pamh);
00109 if (!check_pam_status("startup")) return;
00110
00111 d->status = pam_set_item(d->pamh, PAM_RHOST, rhost);
00112 if (!check_pam_status("environment setup")) return;
00113
00114 d->status = pam_authenticate(d->pamh, PAM_DISALLOW_NULL_AUTHTOK);
00115 if (!check_pam_status("authentication")) return;
00116
00117 d->status = pam_setcred(d->pamh, PAM_ESTABLISH_CRED);
00118 if (!check_pam_status("credentials")) return;
00119
00120 d->status = pam_open_session(d->pamh, 0);
00121 if (!check_pam_status("session open")) return;
00122
00123
00124 if (cloned && !!successmsg) cloned->write(successmsg.cstr(), successmsg.len());
00125
00126
00127 setgrent();
00128 struct group *gr;
00129 while ((gr = getgrent()))
00130 {
00131 for (char **i = gr->gr_mem; *i != NULL; i++)
00132 {
00133 if (strcmp(*i, d->user))
00134 {
00135 d->groups.append(new WvString(gr->gr_name), true);
00136 break;
00137 }
00138 }
00139 }
00140 endgrent();
00141 }
00142
00143
00144 WvPamStream::~WvPamStream()
00145 {
00146 if (d->status == PAM_SUCCESS)
00147 pam_close_session(d->pamh, 0);
00148 pam_end(d->pamh, d->status);
00149 }
00150
00151
00152 bool WvPamStream::isok() const
00153 {
00154 return (d->status == PAM_SUCCESS && WvStreamClone::isok());
00155 }
00156
00157
00158 bool WvPamStream::check_pam_status(WvStringParm s)
00159 {
00160 WvLog log("WvPamStream", WvLog::Debug2);
00161 if (d->status == PAM_SUCCESS)
00162 {
00163 log("PAM %s succeeded\n", s);
00164 return true;
00165 }
00166 else
00167 {
00168 log("PAM %s FAILED: %s\n", s, d->status);
00169 if (cloned && !!d->failmsg) cloned->write(d->failmsg.cstr(), d->failmsg.len());
00170 d->user = WvString::null;
00171 d->groups.zap();
00172 return false;
00173 }
00174 }
00175
00176
00177 WvString WvPamStream::getuser() const
00178 {
00179 return d->user;
00180 }
00181
00182
00183 void WvPamStream::getgroups(WvStringList &l) const
00184 {
00185 assert(l.isempty());
00186 WvStringList::Iter i(d->groups);
00187 for (i.rewind(); i.next(); )
00188 l.append(new WvString(*i), true);
00189 }
00190
00191
00192 #endif // HAVE_SECURITY_PAM_APPL_H