Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

wvpam.cc

Go to the documentation of this file.
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2003 Net Integration Technologies, Inc. 00004 * 00005 * A WvStream that authenticates with PAM before allowing any reading or 00006 * writing. If WvStreams is compiled without PAM, it just fails. 00007 * 00008 * For now, this only works for PAM modules that don't require any user 00009 * interaction. 00010 */ 00011 00012 #include "wvlog.h" 00013 #include "wvpam.h" 00014 #include "wvautoconf.h" 00015 00016 // If PAM not installed at compile time, stub this out 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 /** noconv: null PAM conversation function */ 00078 int noconv(int num_msg, const struct pam_message **msgm, 00079 struct pam_response **response, void *userdata) 00080 { 00081 // if you need to ask things, it won't work 00082 return PAM_CONV_ERR; 00083 } 00084 00085 00086 // FIXME: pam calls could block. Should fork off a subproc for this. On the 00087 // other hand, the stream's blocked anyway until pam comes back, so do we 00088 // really care? 00089 WvPamStream::WvPamStream(WvStream *cloned, WvStringParm name, 00090 WvStringParm successmsg, WvStringParm failmsg) : 00091 WvStreamClone(cloned), 00092 d(new WvPamData(failmsg)) 00093 { 00094 // create the conv structure 00095 struct pam_conv c; 00096 c.conv = noconv; 00097 c.appdata_ptr = NULL; 00098 00099 // find the user 00100 struct passwd *pw = getpwuid(getuid()); 00101 assert(pw); 00102 d->user = pw->pw_name; 00103 00104 // find the host and port 00105 WvString rhost(*src()); 00106 00107 // authenticate through PAM 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 // write the success message if necessary 00124 if (cloned && !!successmsg) cloned->write(successmsg.cstr(), successmsg.len()); 00125 00126 // get the groups 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

Generated on Tue Oct 5 01:09:20 2004 for WvStreams by doxygen 1.3.7