12 #include "pam_private.h"
18 (X) = (Y) ? _pam_strdup(Y) : NULL; \
24 /* handy version id */
26 unsigned int __libpam_version = LIBPAM_VERSION;
30 int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
36 IF_NO_PAMH("pam_set_item", pamh, PAM_SYSTEM_ERR);
43 /* Setting handlers_loaded to 0 will cause the handlers
44 * to be reloaded on the next call to a service module.
46 pamh->handlers.handlers_loaded = 0;
47 RESET(pamh->service_name, item);
50 for (tmp=pamh->service_name; *tmp; ++tmp)
51 *tmp = tolower(*tmp); /* require lower case */
56 RESET(pamh->user, item);
60 RESET(pamh->prompt, item);
64 D(("setting tty to %s", item));
65 RESET(pamh->tty, item);
69 RESET(pamh->ruser, item);
73 RESET(pamh->rhost, item);
78 * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from
81 if (__PAM_FROM_MODULE(pamh)) {
82 char *_TMP_ = pamh->authtok;
83 if (_TMP_ == item) /* not changed so leave alone */
85 pamh->authtok = (item) ? _pam_strdup(item) : NULL;
87 _pam_overwrite(_TMP_);
91 retval = PAM_BAD_ITEM;
98 * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from
101 if (__PAM_FROM_MODULE(pamh)) {
102 char *_TMP_ = pamh->oldauthtok;
103 if (_TMP_ == item) /* not changed so leave alone */
105 pamh->oldauthtok = (item) ? _pam_strdup(item) : NULL;
107 _pam_overwrite(_TMP_);
111 retval = PAM_BAD_ITEM;
116 case PAM_CONV: /* want to change the conversation function */
118 _pam_system_log(LOG_ERR,
119 "pam_set_item: attempt to set conv() to NULL");
120 retval = PAM_PERM_DENIED;
122 struct pam_conv *tconv;
125 (struct pam_conv *) malloc(sizeof(struct pam_conv))
127 _pam_system_log(LOG_CRIT,
128 "pam_set_item: malloc failed for pam_conv");
129 retval = PAM_BUF_ERR;
131 memcpy(tconv, item, sizeof(struct pam_conv));
132 _pam_drop(pamh->pam_conversation);
133 pamh->pam_conversation = tconv;
139 pamh->fail_delay.delay_fn_ptr = item;
143 retval = PAM_BAD_ITEM;
149 int pam_get_item (const pam_handle_t *pamh, int item_type, const void **item)
151 int retval = PAM_SUCCESS;
154 IF_NO_PAMH("pam_get_item", pamh, PAM_SYSTEM_ERR);
157 _pam_system_log(LOG_ERR,
158 "pam_get_item: nowhere to place requested item");
159 return PAM_PERM_DENIED;
164 *item = pamh->service_name;
168 D(("returning user=%s", pamh->user));
172 case PAM_USER_PROMPT:
173 D(("returning userprompt=%s", pamh->user));
174 *item = pamh->prompt;
178 D(("returning tty=%s", pamh->tty));
192 * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from
195 if (__PAM_FROM_MODULE(pamh)) {
196 *item = pamh->authtok;
198 retval = PAM_BAD_ITEM;
204 * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from
207 if (__PAM_FROM_MODULE(pamh)) {
208 *item = pamh->oldauthtok;
210 retval = PAM_BAD_ITEM;
215 *item = pamh->pam_conversation;
219 *item = pamh->fail_delay.delay_fn_ptr;
223 retval = PAM_BAD_ITEM;
230 * This function is the 'preferred method to obtain the username'.
233 int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt)
235 const char *use_prompt;
237 struct pam_message msg,*pmsg;
238 struct pam_response *resp;
241 IF_NO_PAMH("pam_get_user", pamh, PAM_SYSTEM_ERR);
243 if (pamh->pam_conversation == NULL) {
244 _pam_system_log(LOG_ERR, "pam_get_user: no conv element in pamh");
245 return PAM_SERVICE_ERR;
248 if (user == NULL) { /* ensure the the module has suplied a destination */
249 _pam_system_log(LOG_ERR, "pam_get_user: nowhere to record username");
250 return PAM_PERM_DENIED;
254 if (pamh->user) { /* have one so return it */
259 /* will need a prompt */
261 if (use_prompt == NULL) {
262 use_prompt = pamh->prompt;
263 if (use_prompt == NULL) {
264 use_prompt = PAM_DEFAULT_PROMPT;
268 /* If we are resuming an old conversation, we verify that the prompt
269 is the same. Anything else is an error. */
270 if (pamh->former.want_user) {
271 /* must have a prompt to resume with */
272 if (! pamh->former.prompt) {
273 _pam_system_log(LOG_ERR,
274 "pam_get_user: failed to resume with prompt"
279 /* must be the same prompt as last time */
280 if (strcmp(pamh->former.prompt, use_prompt)) {
281 _pam_system_log(LOG_ERR,
282 "pam_get_user: resumed with different prompt");
286 /* ok, we can resume where we left off last time */
287 pamh->former.want_user = PAM_FALSE;
288 _pam_overwrite(pamh->former.prompt);
289 _pam_drop(pamh->former.prompt);
292 /* converse with application -- prompt user for a username */
294 msg.msg_style = PAM_PROMPT_ECHO_ON;
295 msg.msg = use_prompt;
298 retval = pamh->pam_conversation->
299 conv(1, (const struct pam_message **) &pmsg, &resp,
300 pamh->pam_conversation->appdata_ptr);
302 if (retval == PAM_CONV_AGAIN) {
303 /* conversation function is waiting for an event - save state */
304 D(("conversation function is not ready yet"));
305 pamh->former.want_user = PAM_TRUE;
306 pamh->former.prompt = _pam_strdup(use_prompt);
307 } else if (resp == NULL) {
309 * conversation should have given a response
311 D(("pam_get_user: no response provided"));
312 retval = PAM_CONV_ERR;
313 } else if (retval == PAM_SUCCESS) { /* copy the username */
315 * now we set the PAM_USER item -- this was missing from pre.53
316 * releases. However, reading the Sun manual, it is part of
319 RESET(pamh->user, resp->resp);
325 * note 'resp' is allocated by the application and is
326 * correctly free()'d here
328 _pam_drop_reply(resp, 1);
332 return retval; /* pass on any error from conversation */