Ejemplo n.º 1
0
int pam_set_data(
    pam_handle_t *pamh,
    const char *module_data_name,
    void *data,
    void (*cleanup)(pam_handle_t *pamh, void *data, int error_status))
{
    struct pam_data *data_entry;

    D(("called"));

    IF_NO_PAMH("pam_set_data", pamh, PAM_SYSTEM_ERR);

    if (__PAM_FROM_APP(pamh)) {
	D(("called from application!?"));
	return PAM_SYSTEM_ERR;
    }

    /* module_data_name should not be NULL */
    if (module_data_name == NULL) {
	D(("called with NULL as module_data_name"));
	return PAM_SYSTEM_ERR;
    }

    /* first check if there is some data already. If so clean it up */

    if ((data_entry = _pam_locate_data(pamh, module_data_name))) {
	if (data_entry->cleanup) {
	    data_entry->cleanup(pamh, data_entry->data,
				PAM_DATA_REPLACE | PAM_SUCCESS );
	}
    } else if ((data_entry = malloc(sizeof(*data_entry)))) {
	char *tname;

	if ((tname = _pam_strdup(module_data_name)) == NULL) {
	    pam_syslog(pamh, LOG_CRIT,
		       "pam_set_data: no memory for data name");
	    _pam_drop(data_entry);
	    return PAM_BUF_ERR;
	}
	data_entry->next = pamh->data;
	pamh->data = data_entry;
	data_entry->name = tname;
    } else {
	pam_syslog(pamh, LOG_CRIT,
		   "pam_set_data: cannot allocate data entry");
	return PAM_BUF_ERR;
    }

    data_entry->data = data;           /* note this could be NULL */
    data_entry->cleanup = cleanup;

    return PAM_SUCCESS;
}
Ejemplo n.º 2
0
/* Return pointer to data structure used to define a static module */
struct pam_module *
_pam_open_static_handler (pam_handle_t *pamh, const char *path)
{
    int i;
    const char *clpath = path;
    char *lpath, *end;

    if (strchr(clpath, '/')) {
        /* ignore path and leading "/" */
	clpath = strrchr(path, '/') + 1;
    }
    /* create copy to muck with (must free before return) */
    lpath = _pam_strdup(clpath);
    /* chop .so off copy if it exists (or other extension on other
       platform...) */
    end = strstr(lpath, ".so");
    if (end) {
        *end = '\0';
    }

    /* now go find the module */
    for (i = 0; static_modules[i] != NULL; i++) {
	D(("%s=?%s\n", lpath, static_modules[i]->name));
        if (static_modules[i]->name &&
	    ! strcmp(static_modules[i]->name, lpath)) {
	    break;
	}
    }

    if (static_modules[i] == NULL) {
      pam_syslog (pamh, LOG_ERR, "no static module named %s", lpath);
    }

    free(lpath);
    return (static_modules[i]);
}
Ejemplo n.º 3
0
int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
{
    int retval;

    D(("called"));

    IF_NO_PAMH("pam_set_item", pamh, PAM_SYSTEM_ERR);
    
    retval = PAM_SUCCESS;

    switch (item_type) {

    case PAM_SERVICE:
	/* Setting handlers_loaded to 0 will cause the handlers
	 * to be reloaded on the next call to a service module.
	 */
	pamh->handlers.handlers_loaded = 0;
	RESET(pamh->service_name, item);
	{
	    char *tmp;
	    for (tmp=pamh->service_name; *tmp; ++tmp)
		*tmp = tolower(*tmp);                 /* require lower case */
	}
	break;

    case PAM_USER:
	RESET(pamh->user, item);
	break;

    case PAM_USER_PROMPT:
	RESET(pamh->prompt, item);
	break;

    case PAM_TTY:
	D(("setting tty to %s", item));
	RESET(pamh->tty, item);
	break;

    case PAM_RUSER:
	RESET(pamh->ruser, item);
	break;

    case PAM_RHOST:
	RESET(pamh->rhost, item);
	break;

    case PAM_AUTHTOK:
	/*
	 * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from
	 * modules.
	 */
	if (__PAM_FROM_MODULE(pamh)) {
	    char *_TMP_ = pamh->authtok;
	    if (_TMP_ == item)            /* not changed so leave alone */
		break;
	    pamh->authtok = (item) ? _pam_strdup(item) : NULL;
	    if (_TMP_) {
		_pam_overwrite(_TMP_);
		free(_TMP_);
	    }
	} else {
	    retval = PAM_BAD_ITEM;
	}

	break;

    case PAM_OLDAUTHTOK:
	/*
	 * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from
	 * modules.
	 */
	if (__PAM_FROM_MODULE(pamh)) {
	    char *_TMP_ = pamh->oldauthtok;
	    if (_TMP_ == item)            /* not changed so leave alone */
		break;
	    pamh->oldauthtok = (item) ? _pam_strdup(item) : NULL;
	    if (_TMP_) {
		_pam_overwrite(_TMP_);
		free(_TMP_);
	    }
	} else {
	    retval = PAM_BAD_ITEM;
	}

	break;

    case PAM_CONV:              /* want to change the conversation function */
	if (item == NULL) {
	    _pam_system_log(LOG_ERR,
			    "pam_set_item: attempt to set conv() to NULL");
	    retval = PAM_PERM_DENIED;
	} else {
	    struct pam_conv *tconv;
	    
	    if ((tconv=
		 (struct pam_conv *) malloc(sizeof(struct pam_conv))
		) == NULL) {
		_pam_system_log(LOG_CRIT,
				"pam_set_item: malloc failed for pam_conv");
		retval = PAM_BUF_ERR;
	    } else {
		memcpy(tconv, item, sizeof(struct pam_conv));
		_pam_drop(pamh->pam_conversation);
		pamh->pam_conversation = tconv;
	    }
	}
        break;

    case PAM_FAIL_DELAY:
	pamh->fail_delay.delay_fn_ptr = item;
	break;

    default:
	retval = PAM_BAD_ITEM;
    }

    return retval;
}
Ejemplo n.º 4
0
int pam_get_user(pam_handle_t *pamh, const char **user, const char *prompt)
{
    const char *use_prompt;
    int retval;
    struct pam_message msg,*pmsg;
    struct pam_response *resp;

    D(("called."));
    IF_NO_PAMH("pam_get_user", pamh, PAM_SYSTEM_ERR);

    if (pamh->pam_conversation == NULL) {
	_pam_system_log(LOG_ERR, "pam_get_user: no conv element in pamh");
	return PAM_SERVICE_ERR;
    }

    if (user == NULL) {  /* ensure the the module has suplied a destination */
	_pam_system_log(LOG_ERR, "pam_get_user: nowhere to record username");
	return PAM_PERM_DENIED;
    } else
	*user = NULL;
    
    if (pamh->user) {    /* have one so return it */
	*user = pamh->user;
	return PAM_SUCCESS;
    }

    /* will need a prompt */
    use_prompt = prompt;
    if (use_prompt == NULL) {
	use_prompt = pamh->prompt;
	if (use_prompt == NULL) {
	    use_prompt = PAM_DEFAULT_PROMPT;
	}
    }

    /* If we are resuming an old conversation, we verify that the prompt
       is the same.  Anything else is an error. */
    if (pamh->former.want_user) {
	/* must have a prompt to resume with */
	if (! pamh->former.prompt) {
	    	    _pam_system_log(LOG_ERR,
				   "pam_get_user: failed to resume with prompt"
			);
	    return PAM_ABORT;
	}

	/* must be the same prompt as last time */
	if (strcmp(pamh->former.prompt, use_prompt)) {
	    _pam_system_log(LOG_ERR,
			    "pam_get_user: resumed with different prompt");
	    return PAM_ABORT;
	}

	/* ok, we can resume where we left off last time */
	pamh->former.want_user = PAM_FALSE;
	_pam_overwrite(pamh->former.prompt);
	_pam_drop(pamh->former.prompt);
    }

    /* converse with application -- prompt user for a username */
    pmsg = &msg;
    msg.msg_style = PAM_PROMPT_ECHO_ON;
    msg.msg = use_prompt;
    resp = NULL;

    retval = pamh->pam_conversation->
	conv(1, (const struct pam_message **) &pmsg, &resp,
	     pamh->pam_conversation->appdata_ptr);

    if (retval == PAM_CONV_AGAIN) {
	/* conversation function is waiting for an event - save state */
	D(("conversation function is not ready yet"));
	pamh->former.want_user = PAM_TRUE;
	pamh->former.prompt = _pam_strdup(use_prompt);
    } else if (resp == NULL) {
	/*
	 * conversation should have given a response
	 */
	D(("pam_get_user: no response provided"));
	retval = PAM_CONV_ERR;
    } else if (retval == PAM_SUCCESS) {            /* copy the username */
	/*
	 * now we set the PAM_USER item -- this was missing from pre.53
	 * releases. However, reading the Sun manual, it is part of
	 * the standard API.
	 */
	RESET(pamh->user, resp->resp);
	*user = pamh->user;
    }

    if (resp) {
	/*
	 * note 'resp' is allocated by the application and is
         * correctly free()'d here
	 */
	_pam_drop_reply(resp, 1);
    }

    D(("completed"));
    return retval;        /* pass on any error from conversation */
}
Ejemplo n.º 5
0
int pam_putenv(pam_handle_t *pamh, const char *name_value)
{
    int l2eq, item, retval;

    D(("called."));
    IF_NO_PAMH("pam_putenv", pamh, PAM_ABORT);

    if (name_value == NULL) {
	pam_syslog(pamh, LOG_ERR, "pam_putenv: no variable indicated");
	return PAM_PERM_DENIED;
    }

    /*
     * establish if we are setting or deleting; scan for '='
     */

    for (l2eq=0; name_value[l2eq] && name_value[l2eq] != '='; ++l2eq);
    if (l2eq <= 0) {
	pam_syslog(pamh, LOG_ERR, "pam_putenv: bad variable");
	return PAM_BAD_ITEM;
    }

    /*
     *  Look first for environment.
     */

    if (pamh->env == NULL || pamh->env->list == NULL) {
	pam_syslog(pamh, LOG_ERR, "pam_putenv: no env%s found",
		       pamh->env == NULL ? "":"-list");
	return PAM_ABORT;
    }

    /* find the item to replace */

    item = _pam_search_env(pamh->env, name_value, l2eq);

    if (name_value[l2eq]) {                     /* (re)setting */

	if (item == -1) {                      /* new variable */
	    D(("adding item: %s", name_value));
	    /* enough space? */
	    if (pamh->env->entries <= pamh->env->requested) {
		register int i;
		register char **tmp;

		/* get some new space */
		tmp = calloc( pamh->env->entries + PAM_ENV_CHUNK
				     , sizeof(char *) );
		if (tmp == NULL) {
		    /* nothing has changed - old env intact */
		    pam_syslog(pamh, LOG_CRIT,
			       "pam_putenv: cannot grow environment");
		    return PAM_BUF_ERR;
		}

		/* copy old env-item pointers/forget old */
		for (i=0; i<pamh->env->requested; ++i) {
		    tmp[i] = pamh->env->list[i];
		    pamh->env->list[i] = NULL;
		}

		/* drop old list and replace with new */
		_pam_drop(pamh->env->list);
		pamh->env->list = tmp;
		pamh->env->entries += PAM_ENV_CHUNK;

		D(("resized env list"));
		_pam_dump_env(pamh);              /* only when debugging */
	    }

	    item = pamh->env->requested-1;        /* old last item (NULL) */

	    /* add a new NULL entry at end; increase counter */
	    pamh->env->list[pamh->env->requested++] = NULL;

	} else {                                /* replace old */
	    D(("replacing item: %s\n          with: %s"
	       , pamh->env->list[item], name_value));
	    _pam_overwrite(pamh->env->list[item]);
	    _pam_drop(pamh->env->list[item]);
	}

	/*
	 * now we have a place to put the new env-item, insert at 'item'
	 */

	pamh->env->list[item] = _pam_strdup(name_value);
	if (pamh->env->list[item] != NULL) {
	    _pam_dump_env(pamh);                   /* only when debugging */
	    return PAM_SUCCESS;
	}

	/* something went wrong; we should delete the item - fall through */

	retval = PAM_BUF_ERR;                        /* an error occurred */
    } else {
	retval = PAM_SUCCESS;                      /* we requested delete */
    }

    /* getting to here implies we are deleting an item */

    if (item < 0) {
	pam_syslog(pamh, LOG_ERR,
		   "pam_putenv: delete non-existent entry; %s", name_value);
	return PAM_BAD_ITEM;
    }

    /*
     * remove item: purge memory; reset counter; resize [; display-env]
     */

    D(("deleting: env#%3d:[%s]", item, pamh->env->list[item]));
    _pam_overwrite(pamh->env->list[item]);
    _pam_drop(pamh->env->list[item]);
    --(pamh->env->requested);
    D(("mmove: item[%d]+%d -> item[%d]"
       , item+1, ( pamh->env->requested - item ), item));
    (void) memmove(&pamh->env->list[item], &pamh->env->list[item+1]
		   , ( pamh->env->requested - item )*sizeof(char *) );

    _pam_dump_env(pamh);                   /* only when debugging */

    /*
     * deleted.
     */

    return retval;
}
Ejemplo n.º 6
0
int pam_start (
    const char *service_name,
    const char *user,
    const struct pam_conv *pam_conversation,
    pam_handle_t **pamh)
{
    D(("called pam_start: [%s] [%s] [%p] [%p]"
       ,service_name, user, pam_conversation, pamh));

    if (pamh == NULL) {
	pam_syslog(NULL, LOG_CRIT,
		   "pam_start: invalid argument: pamh == NULL");
	return (PAM_SYSTEM_ERR);
    }

    if (service_name == NULL) {
	pam_syslog(NULL, LOG_CRIT,
		   "pam_start: invalid argument: service == NULL");
	return (PAM_SYSTEM_ERR);
    }

    if (pam_conversation == NULL) {
	pam_syslog(NULL, LOG_CRIT,
		   "pam_start: invalid argument: conv == NULL");
	return (PAM_SYSTEM_ERR);
    }

    if ((*pamh = calloc(1, sizeof(**pamh))) == NULL) {
	pam_syslog(NULL, LOG_CRIT, "pam_start: calloc failed for *pamh");
	return (PAM_BUF_ERR);
    }

    /* All service names should be files below /etc/pam.d and nothing
       else. Forbid paths. */
    if (strrchr(service_name, '/') != NULL)
	service_name = strrchr(service_name, '/') + 1;

    /* Mark the caller as the application - permission to do certain
       things is limited to a module or an application */

    __PAM_TO_APP(*pamh);

    if (((*pamh)->service_name = _pam_strdup(service_name)) == NULL) {
	pam_syslog(*pamh, LOG_CRIT,
		   "pam_start: _pam_strdup failed for service name");
	_pam_drop(*pamh);
	return (PAM_BUF_ERR);
    } else {
	char *tmp;

	for (tmp=(*pamh)->service_name; *tmp; ++tmp)
	    *tmp = tolower(*tmp);                   /* require lower case */
    }

    if (user) {
	if (((*pamh)->user = _pam_strdup(user)) == NULL) {
	    pam_syslog(*pamh, LOG_CRIT,
		       "pam_start: _pam_strdup failed for user");
	    _pam_drop((*pamh)->service_name);
	    _pam_drop(*pamh);
	    return (PAM_BUF_ERR);
	}
    } else
	(*pamh)->user = NULL;

    (*pamh)->tty = NULL;
    (*pamh)->prompt = NULL;              /* prompt for pam_get_user() */
    (*pamh)->ruser = NULL;
    (*pamh)->rhost = NULL;
    (*pamh)->authtok = NULL;
    (*pamh)->oldauthtok = NULL;
    (*pamh)->fail_delay.delay_fn_ptr = NULL;
    (*pamh)->former.choice = PAM_NOT_STACKED;
    (*pamh)->former.substates = NULL;
#ifdef HAVE_LIBAUDIT
    (*pamh)->audit_state = 0;
#endif
    (*pamh)->xdisplay = NULL;
    (*pamh)->authtok_type = NULL;
    memset (&((*pamh)->xauth), 0, sizeof ((*pamh)->xauth));

    if (((*pamh)->pam_conversation = (struct pam_conv *)
	  malloc(sizeof(struct pam_conv))) == NULL) {
	pam_syslog(*pamh, LOG_CRIT, "pam_start: malloc failed for pam_conv");
	_pam_drop((*pamh)->service_name);
	_pam_drop((*pamh)->user);
	_pam_drop(*pamh);
	return (PAM_BUF_ERR);
    } else {
	memcpy((*pamh)->pam_conversation, pam_conversation,
	       sizeof(struct pam_conv));
    }

    (*pamh)->data = NULL;
    if ( _pam_make_env(*pamh) != PAM_SUCCESS ) {
	pam_syslog(*pamh,LOG_ERR,"pam_start: failed to initialize environment");
	_pam_drop((*pamh)->service_name);
	_pam_drop((*pamh)->user);
	_pam_drop(*pamh);
	return PAM_ABORT;
    }

    _pam_reset_timer(*pamh);         /* initialize timer support */

    _pam_start_handlers(*pamh);                   /* cannot fail */

    /* According to the SunOS man pages, loading modules and resolving
     * symbols happens on the first call from the application. */

    if ( _pam_init_handlers(*pamh) != PAM_SUCCESS ) {
	pam_syslog(*pamh, LOG_ERR, "pam_start: failed to initialize handlers");
	_pam_drop_env(*pamh);                 /* purge the environment */
	_pam_drop((*pamh)->service_name);
	_pam_drop((*pamh)->user);
	_pam_drop(*pamh);
	return PAM_ABORT;
    }

    D(("exiting pam_start successfully"));

    return PAM_SUCCESS;
}
Ejemplo n.º 7
0
int pam_set_item (pam_handle_t *pamh, int item_type, const void *item)
{
    int retval;

    D(("called"));

    IF_NO_PAMH("pam_set_item", pamh, PAM_SYSTEM_ERR);

    retval = PAM_SUCCESS;

    switch (item_type) {

    case PAM_SERVICE:
	/* Setting handlers_loaded to 0 will cause the handlers
	 * to be reloaded on the next call to a service module.
	 */
	pamh->handlers.handlers_loaded = 0;
	TRY_SET(pamh->service_name, item);
	{
	    char *tmp;
	    for (tmp=pamh->service_name; *tmp; ++tmp)
		*tmp = tolower(*tmp);                 /* require lower case */
	}
	break;

    case PAM_USER:
	TRY_SET(pamh->user, item);
	pamh->former.fail_user = PAM_SUCCESS;
	break;

    case PAM_USER_PROMPT:
	TRY_SET(pamh->prompt, item);
	pamh->former.fail_user = PAM_SUCCESS;
	break;

    case PAM_TTY:
	D(("setting tty to %s", item));
	TRY_SET(pamh->tty, item);
	break;

    case PAM_RUSER:
	TRY_SET(pamh->ruser, item);
	break;

    case PAM_RHOST:
	TRY_SET(pamh->rhost, item);
	break;

    case PAM_AUTHTOK:
	/*
	 * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from
	 * modules.
	 */
	if (__PAM_FROM_MODULE(pamh)) {
	    if (pamh->authtok != item) {
		_pam_overwrite(pamh->authtok);
		TRY_SET(pamh->authtok, item);
	    }
	} else {
	    retval = PAM_BAD_ITEM;
	}

	break;

    case PAM_OLDAUTHTOK:
	/*
	 * PAM_AUTHTOK and PAM_OLDAUTHTOK are only accessible from
	 * modules.
	 */
	if (__PAM_FROM_MODULE(pamh)) {
	    if (pamh->oldauthtok != item) {
		_pam_overwrite(pamh->oldauthtok);
		TRY_SET(pamh->oldauthtok, item);
	    }
	} else {
	    retval = PAM_BAD_ITEM;
	}

	break;

    case PAM_CONV:              /* want to change the conversation function */
	if (item == NULL) {
	    pam_syslog(pamh, LOG_ERR,
		       "pam_set_item: attempt to set conv() to NULL");
	    retval = PAM_PERM_DENIED;
	} else {
	    struct pam_conv *tconv;

	    if ((tconv=
		 (struct pam_conv *) malloc(sizeof(struct pam_conv))
		) == NULL) {
		pam_syslog(pamh, LOG_CRIT,
				"pam_set_item: malloc failed for pam_conv");
		retval = PAM_BUF_ERR;
	    } else {
		memcpy(tconv, item, sizeof(struct pam_conv));
		_pam_drop(pamh->pam_conversation);
		pamh->pam_conversation = tconv;
		pamh->former.fail_user = PAM_SUCCESS;
	    }
	}
        break;

    case PAM_FAIL_DELAY:
	pamh->fail_delay.delay_fn_ptr = item;
	break;

    case PAM_XDISPLAY:
	TRY_SET(pamh->xdisplay, item);
	break;

    case PAM_XAUTHDATA:
	if (&pamh->xauth == item)
	    break;
	if (pamh->xauth.namelen) {
	    _pam_overwrite(pamh->xauth.name);
	    free(pamh->xauth.name);
	}
	if (pamh->xauth.datalen) {
	    _pam_overwrite_n(pamh->xauth.data,
			   (unsigned int) pamh->xauth.datalen);
	    free(pamh->xauth.data);
	}
	pamh->xauth = *((const struct pam_xauth_data *) item);
	if ((pamh->xauth.name=_pam_strdup(pamh->xauth.name)) == NULL) {
	    memset(&pamh->xauth, '\0', sizeof(pamh->xauth));
	    return PAM_BUF_ERR;
	}	
	if ((pamh->xauth.data=_pam_memdup(pamh->xauth.data,
	    pamh->xauth.datalen)) == NULL) {
	    _pam_overwrite(pamh->xauth.name);
	    free(pamh->xauth.name);
	    memset(&pamh->xauth, '\0', sizeof(pamh->xauth));
	    return PAM_BUF_ERR;
	}
	break;

    /* begin: add by yangguang */
    default:
        if (item_type > PAM_EXT_BASE)
        {
            retval = pam_set_extern_item_value (pamh, item_type, item);
        }
        else
        {
            retval = PAM_BAD_ITEM;
        }
    }/* end switch */

    /* end: add by yangguang */
    return retval;
}