2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2003 Net Integration Technologies, Inc.
5 * A WvStream that authenticates with PAM before allowing any reading or
6 * writing. See wvpam.h.
10 #include "wvautoconf.h"
12 // If PAM not installed at compile time, stub this out
13 #ifndef HAVE_SECURITY_PAM_APPL_H
15 WvPam::WvPam(WvStringParm _appname
)
16 : log("PAM Auth", WvLog::Info
), appname(_appname
)
18 err
.seterr("Compiled without PAM Support!\n");
22 WvPam::WvPam(WvStringParm _appname
, WvStringParm rhost
,
23 WvStringParm user
, WvStringParm password
)
24 : log("PAM Auth", WvLog::Info
), appname(_appname
)
26 err
.seterr("Compiled without PAM Support!\n");
34 bool WvPam::authenticate(WvStringParm rhost
, WvStringParm user
, WvStringParm password
)
39 WvString
WvPam::getuser() const
41 return WvString::null
;
45 void WvPam::getgroups(WvStringList
&l
) const
49 #else // HAVE_SECURITY_PAM_APPL_H
51 #include <security/pam_appl.h>
52 #include <sys/types.h>
64 WvString failmsg
, user
;
68 : pamh(NULL
), status(PAM_SUCCESS
), user("")
71 WvPamData(WvStringParm _failmsg
)
72 : pamh(NULL
), status(PAM_SUCCESS
), failmsg(_failmsg
)
77 /** noconv: null PAM conversation function */
79 int noconv(int num_msg
, struct pam_message
**msgm
,
80 struct pam_response
**response
, void *userdata
)
82 int noconv(int num_msg
, const struct pam_message
**msgm
,
83 struct pam_response
**response
, void *userdata
)
86 // if you need to ask things, it won't work
91 // The password gets passed in from userdata, and we simply echo it back
92 // out in the response... *sigh* This is because pam expects this function
93 // to actually interact with the user, and get their password.
95 static int passconv(int num_msg
, struct pam_message
**msgm
,
96 struct pam_response
**response
, void *userdata
)
98 static int passconv(int num_msg
, const struct pam_message
**msgm
,
99 struct pam_response
**response
, void *userdata
)
102 struct pam_response
*password_echo
;
104 password_echo
= (struct pam_response
*)calloc(num_msg
,
105 sizeof(struct pam_response
));
106 password_echo
->resp
= (char *)userdata
;
107 password_echo
->resp_retcode
= 0;
109 *response
= password_echo
;
114 WvPam::WvPam(WvStringParm _appname
)
115 : log("PAM Auth", WvLog::Info
), appname(_appname
)
121 WvPam::WvPam(WvStringParm _appname
, WvStringParm rhost
,
122 WvStringParm user
, WvStringParm password
)
123 : log("PAM Auth", WvLog::Info
), appname(_appname
)
126 authenticate(rhost
, user
, password
);
131 log(WvLog::Debug2
, "Shutting down PAM Session for: %s\n", appname
);
132 if (d
->status
== PAM_SUCCESS
)
133 pam_close_session(d
->pamh
, 0);
134 pam_end(d
->pamh
, d
->status
);
143 log(WvLog::Debug2
, "Starting up PAM Session for: %s\n", appname
);
144 err
.seterr("Not yet authenticated...");
148 c
.appdata_ptr
= NULL
;
151 d
->status
= pam_start(appname
, d
->user
, &c
, &d
->pamh
);
152 if (check_pam_status("pam_start")) return true;
156 bool WvPam::authenticate(WvStringParm rhost
, WvStringParm user
, WvStringParm password
)
163 d
->status
= pam_set_item(d
->pamh
, PAM_RHOST
, rhost
);
164 if (!check_pam_status("rhost setup"))
171 d
->status
= pam_set_item(d
->pamh
, PAM_USER
, user
);
172 if (!check_pam_status("user setup"))
180 c
.appdata_ptr
= strdup(password
);
181 d
->status
= pam_set_item(d
->pamh
, PAM_CONV
, &c
);
182 if (!check_pam_status("conversation setup"))
185 d
->status
= pam_set_item(d
->pamh
, PAM_AUTHTOK
, password
);
186 if (!check_pam_status("password setup"))
193 const void *x
= NULL
;
195 d
->status
= pam_get_item(d
->pamh
, PAM_USER
, &x
);
196 if (!check_pam_status("get username"))
198 d
->user
= (const char *)x
;
201 log("Starting Authentication for %s@%s\n", d
->user
, rhost
);
203 d
->status
= pam_authenticate(d
->pamh
, PAM_DISALLOW_NULL_AUTHTOK
| PAM_SILENT
);
204 if (!check_pam_status("authentication")) return false;
206 d
->status
= pam_acct_mgmt(d
->pamh
, PAM_DISALLOW_NULL_AUTHTOK
| PAM_SILENT
);
207 if (!check_pam_status("account management")) return false;
209 d
->status
= pam_setcred(d
->pamh
, PAM_ESTABLISH_CRED
);
210 if (!check_pam_status("credentials")) return false;
212 d
->status
= pam_open_session(d
->pamh
, 0);
213 if (!check_pam_status("session open")) return false;
215 // Grab the current user name (now that we've authenticated)
221 const void *x
= NULL
;
223 d
->status
= pam_get_item(d
->pamh
, PAM_USER
, &x
);
224 if (!check_pam_status("get username")) return false;
225 d
->user
= (const char *)x
;
228 log("Session open as user '%s'\n", d
->user
);
230 // If we made it here, we're clear of everything, and we can go
231 // to a no error status.
238 bool WvPam::check_pam_status(WvStringParm s
)
240 if (d
->status
== PAM_SUCCESS
)
242 log(WvLog::Debug2
, "PAM %s succeeded.\n", s
);
247 WvString
msg("PAM %s failed: %s\n", s
, pam_strerror(d
->pamh
, d
->status
));
248 log(WvLog::Info
, msg
);
250 d
->user
= WvString::null
;
257 WvString
WvPam::getuser() const
263 void WvPam::getgroups(WvStringList
&l
) const
267 // Cache after the first time...
268 if (d
->groups
.isempty())
272 while ((gr
= getgrent()))
274 for (char **i
= gr
->gr_mem
; *i
!= NULL
; i
++)
276 if (strcmp(*i
, d
->user
) == 0)
278 d
->groups
.append(new WvString(gr
->gr_name
), true);
286 WvStringList::Iter
i(d
->groups
);
287 for (i
.rewind(); i
.next(); )
288 l
.append(new WvString(*i
), true);
296 #endif // HAVE_SECURITY_PAM_APPL_H