4 * $Id: pam_item.c,v 1.8 1997/02/15 15:58:49 morgan Exp morgan $
5 * $FreeBSD: src/contrib/libpam/libpam/pam_item.c,v 1.1.1.1.6.2 2001/06/11 15:28:12 markm Exp $
6 * $DragonFly: src/contrib/libpam/libpam/Attic/pam_item.c,v 1.2 2003/06/17 04:24:03 dillon Exp $
16 #include "pam_private.h"
22 (X) = (Y) ? _pam_strdup(Y) : NULL; \
39 IF_NO_PAMH("pam_set_item", pamh, PAM_SYSTEM_ERR);
45 /* Setting handlers_loaded to 0 will cause the handlers
46 * to be reloaded on the next call to a service module.
48 pamh->handlers.handlers_loaded = 0;
49 RESET(pamh->service_name, item);
52 for (tmp=pamh->service_name; *tmp; ++tmp)
53 *tmp = tolower(*tmp); /* require lower case */
57 RESET(pamh->user, item);
60 RESET(pamh->prompt, item);
63 D(("setting tty to %s", item));
64 RESET(pamh->tty, item);
67 RESET(pamh->ruser, item);
70 RESET(pamh->rhost, item);
74 * The man page says this is only supposed to be available to
75 * the module providers. In order to use this item the app
76 * has to #include <security/pam_modules.h>. This is something
77 * it is *not* supposed to do with "Linux-"PAM! - AGM.
80 char *_TMP_ = pamh->authtok;
81 if (_TMP_ == item) /* not changed so leave alone */
83 pamh->authtok = (item) ? _pam_strdup(item) : NULL;
85 _pam_overwrite(_TMP_);
93 char *_TMP_ = pamh->oldauthtok;
94 if (_TMP_ == item) /* not changed so leave alone */
96 pamh->oldauthtok = (item) ? _pam_strdup(item) : NULL;
98 _pam_overwrite(_TMP_);
103 case PAM_CONV: /* want to change the conversation function */
105 pam_system_log(pamh, NULL, LOG_ERR,
106 "pam_set_item: attempt to set conv() to NULL");
107 retval = PAM_PERM_DENIED;
109 struct pam_conv *tconv;
112 (struct pam_conv *) malloc(sizeof(struct pam_conv))
114 pam_system_log(pamh, NULL, LOG_CRIT,
115 "pam_set_item: malloc failed for pam_conv");
116 retval = PAM_BUF_ERR;
118 memcpy(tconv, item, sizeof(struct pam_conv));
119 _pam_drop(pamh->pam_conversation);
120 pamh->pam_conversation = tconv;
125 pamh->fail_delay.delay_fn_ptr = item;
129 char *old_ident = pamh->pam_default_log.ident;
132 /* reset the default state */
133 pamh->pam_default_log.ident = x_strdup(PAM_LOG_STATE_IDENT);
134 pamh->pam_default_log.option = PAM_LOG_STATE_OPTION;
135 pamh->pam_default_log.facility = PAM_LOG_STATE_FACILITY;
137 const struct pam_log_state *state = item;
139 pamh->pam_default_log.ident = x_strdup(state->ident);
140 pamh->pam_default_log.option = state->option;
141 pamh->pam_default_log.facility = state->facility;
143 _pam_overwrite(old_ident);
144 _pam_drop(old_ident);
149 retval = PAM_BAD_ITEM;
156 const pam_handle_t *pamh,
161 IF_NO_PAMH("pam_get_item",pamh,PAM_SYSTEM_ERR);
164 pam_system_log(pamh, NULL, LOG_ERR,
165 "pam_get_item: nowhere to place requested item");
166 return PAM_PERM_DENIED;
171 *item = pamh->service_name;
176 case PAM_USER_PROMPT:
177 *item = pamh->prompt;
180 D(("returning tty=%s", pamh->tty));
190 *item = pamh->authtok;
193 *item = pamh->oldauthtok;
196 *item = pamh->pam_conversation;
199 *item = pamh->fail_delay.delay_fn_ptr;
202 *item = &(pamh->pam_default_log);
205 /* XXX - I made this up */
212 /* added by AGM 1996/3/2 */
214 int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt)
216 const char *use_prompt;
218 struct pam_message msg,*pmsg;
219 struct pam_response *resp;
222 IF_NO_PAMH("pam_get_user", pamh, PAM_SYSTEM_ERR);
224 if (pamh->pam_conversation == NULL) {
225 pam_system_log(pamh, NULL, LOG_ERR,
226 "pam_get_user: no conv element in pamh");
227 return PAM_SERVICE_ERR;
230 if (user == NULL) { /* ensure the the module has suplied a destination */
231 pam_system_log(pamh, NULL, LOG_ERR,
232 "pam_get_user: nowhere to record username");
233 return PAM_PERM_DENIED;
237 if (pamh->user) { /* have one so return it */
242 /* will need a prompt */
244 if (use_prompt == NULL) {
245 use_prompt = pamh->prompt;
246 if (use_prompt == NULL) {
247 use_prompt = PAM_DEFAULT_PROMPT;
251 /* If we are resuming an old conversation, we verify that the prompt
252 is the same. Anything else is an error. */
253 if (pamh->former.want_user) {
254 /* must have a prompt to resume with */
255 if (! pamh->former.prompt) {
256 pam_system_log(pamh, NULL, LOG_ERR,
257 "pam_get_user: failed to resume with prompt"
262 /* must be the same prompt as last time */
263 if (strcmp(pamh->former.prompt, use_prompt)) {
264 pam_system_log(pamh, NULL, LOG_ERR,
265 "pam_get_user: resumed with different prompt");
269 /* ok, we can resume where we left off last time */
270 pamh->former.want_user = PAM_FALSE;
271 _pam_overwrite(pamh->former.prompt);
272 _pam_drop(pamh->former.prompt);
275 /* converse with application -- prompt user for a username */
277 msg.msg_style = PAM_PROMPT_ECHO_ON;
278 msg.msg = use_prompt;
281 retval = pamh->pam_conversation->
282 conv(1, (const struct pam_message **) &pmsg, &resp,
283 pamh->pam_conversation->appdata_ptr);
285 if (retval == PAM_CONV_AGAIN) {
286 /* conversation function is waiting for an event - save state */
287 D(("conversation function is not ready yet"));
288 pamh->former.want_user = PAM_TRUE;
289 pamh->former.prompt = _pam_strdup(use_prompt);
290 } else if (resp == NULL) {
292 * conversation should have given a response
294 D(("pam_get_user: no response provided"));
295 retval = PAM_CONV_ERR;
296 } else if (retval == PAM_SUCCESS) { /* copy the username */
298 * now we set the PAM_USER item -- this was missing from pre.53
299 * releases. However, reading the Sun manual, it is part of
302 RESET(pamh->user, resp->resp);
308 * note 'resp' is allocated by the application and is
309 * correctly free()'d here
311 _pam_drop_reply(resp, 1);
314 return retval; /* pass on any error from conversation */