Ejemplo n.º 1
0
ni_status ni2_destroy(void *domain, char *pathname)
{
    /* destroy a directory */
    /* this version recursively destroys all subdirectories as well */

    ni_status ret;
    ni_id dir, parent;
    ni_index pi;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if the directory exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    /* get the parent directory index (nii_object) */
    ret = ni_parent(domain, &dir, &pi);
    if (ret != NI_OK) return ret;

    /* get the parent directory id */
    parent.nii_object = pi;
    ret = ni_self(domain, &parent);
    if (ret != NI_OK) return ret;

    return ni2_destroydir(domain, &dir, &parent);
}
Ejemplo n.º 2
0
ni_status ni2_renamedirprop(void *domain, ni_id *dir, const ni_name oldname, const ni_name newname)
{
    /* renameprop given a directory rather than a pathname */

    ni_status ret;
    ni_index where;
    ni_namelist nl;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* look up old name */
    where = ni_namelist_match(nl, oldname);
    ni_namelist_free(&nl);

    /* if it's not there, return an error */
    if (where == NI_INDEX_NULL) {
        return NI_NOPROP;
    }

    return ni_renameprop(domain, dir, where, newname);
}
Ejemplo n.º 3
0
ni_status ni2_destroydir(void *domain, ni_id *dir, ni_id *parent)
{
    /* destroy a directory and all it's subdirectories */
    /* this is the recursive workhorse */

    ni_status ret;
    int i;
    ni_idlist children;
    ni_id child;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* get a list of all my children */
    NI_INIT(&children);
    ret = ni_children(domain, dir, &children);
    if (ret != NI_OK) return ret;

    /* destroy each child */
    for (i = 0; i < children.ni_idlist_len; i++) {
        child.nii_object = children.ni_idlist_val[i];
        ret = ni_self(domain, &child);
        if (ret != NI_OK) return ret;
        ret = ni2_destroydir(domain, &child, dir);
        if (ret != NI_OK) return ret;
    }

    /* free list of child ids */
    ni_idlist_free(&children);

    /* destroy myself */
    return ni_destroy(domain, parent, *dir);
}
Ejemplo n.º 4
0
ni_status ni2_mergedirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
    /* mergeprop given a directory rather than a pathname */

    ni_status ret;
    ni_property p;
    ni_namelist nl;
    ni_index where, whereval;
    int i;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for existing property with this key */
    where = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, create it */
    if (where == NI_INDEX_NULL) {
        NI_INIT(&p);
        p.nip_name = ni_name_dup(key);
        p.nip_val = ni_namelist_dup(values);
        ret = ni_createprop(domain, dir, p, NI_INDEX_NULL);
        ni_prop_free(&p);
        return ret;
    }


    /* property exists: replace the existing values */
    /* fetch existing namelist for this property */
    NI_INIT(&nl);
    ret = ni_readprop(domain, dir, where, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* merge new values */
    for (i = 0; i < values.ni_namelist_len; i++) {
        whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
        if (whereval == NI_INDEX_NULL) {
            ni_namelist_insert(&nl, values.ni_namelist_val[i], NI_INDEX_NULL);
        }
    }

    /* write the new list back */
    ret = ni_writeprop(domain, dir, where, nl);
    ni_namelist_free(&nl);
    return ret;
}
Ejemplo n.º 5
0
ni_status ni2_destroydirval(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
    /* destroyval given a directory rather than a pathname */

    ni_status ret;
    ni_namelist nl;
    ni_index where, whereval;
    int i;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for existing property with this key */
    where = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, nothing to do */
    if (where == NI_INDEX_NULL) {
        return NI_OK;
    }

    /* fetch existing namelist for this property */
    NI_INIT(&nl);
    ret = ni_readprop(domain, dir, where, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* delete values */
    for (i = 0; i < values.ni_namelist_len; i++) {
        whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
        while (whereval != NI_INDEX_NULL) {
            ni_namelist_delete(&nl, whereval);
            whereval = ni_namelist_match(nl, values.ni_namelist_val[i]);
        }
    }

    /* write the new list back */
    ret = ni_writeprop(domain, dir, where, nl);
    ni_namelist_free(&nl);

    return ret;
}
Ejemplo n.º 6
0
ni_status ni2_renameprop(void *domain, char *pathname, const ni_name oldname, const ni_name newname)
{
    /* rename a property */

    ni_status ret;
    ni_id dir;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if the directory already exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    return ni2_renamedirprop(domain, &dir, oldname, newname);
}
Ejemplo n.º 7
0
ni_status ni2_destroyval(void *domain, char *pathname, const ni_name key, ni_namelist values)
{
    /* destroy all occurances of a value in a property */

    ni_status ret;
    ni_id dir;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if the directory exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    return ni2_destroydirval(domain, &dir, key, values);
}
Ejemplo n.º 8
0
ni_status ni2_destroyprop(void *domain, char *pathname, ni_namelist keys)
{
    /* destroy a property */
    /* destroys all properties with the same key */

    ni_status ret;
    ni_id dir;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if the directory exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    return ni2_destroydirprop(domain, &dir, keys);
}
Ejemplo n.º 9
0
ni_status ni2_mergeprop(void *domain, char *pathname, const ni_name key, ni_namelist values)
{
    /* merge a list of values into a property (to prevent duplicates) */
    /* creates the property if it doesn't already exist */

    ni_status ret;
    ni_id dir;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if the directory already exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    return ni2_mergedirprop(domain, &dir, key, values);
}
Ejemplo n.º 10
0
ni_status ni2_insertval(void *domain, char *pathname, const ni_name key, const ni_name value, ni_index where)
{
    /* insert a new value into a property */
    /* the property is created if it doesn't exist */

    ni_status ret;
    ni_id dir;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if the directory exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    return ni2_insertdirval(domain, &dir, key, value, where);
}
Ejemplo n.º 11
0
ni_status ni2_appendprop(void *domain, char *pathname, const ni_name key, ni_namelist values)
{
    /* append a list of values to a property */
    /* a new property is created if it doesn't exist */

    ni_status ret;
    ni_id dir;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if the directory already exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    return ni2_appenddirprop(domain, &dir, key, values);
}
Ejemplo n.º 12
0
ni_status ni2_createprop(void *domain, char *pathname, const ni_name key, ni_namelist values)
{
    /* create a new property with a given key and list of values */
    /* replaces an existing property if it already exists */

    ni_status ret;
    ni_id dir;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if the directory already exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret != NI_OK) return ret;

    return ni2_createdirprop(domain, &dir, key, values);
}
Ejemplo n.º 13
0
ni_status ni2_destroydirprop(void *domain, ni_id *dir, ni_namelist keys)
{
    /* destroyprop given a directory rather than a pathname */

    ni_status ret;
    ni_index where;
    ni_namelist nl;
    int i;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* destroy all occurrences of each key */
    for (i = 0; i < keys.ni_namelist_len; i++) {

        where = ni_namelist_match(nl, keys.ni_namelist_val[i]);

        /* keep looking for all occurrences */
        while (where != NI_INDEX_NULL) {
            ret = ni_destroyprop(domain, dir, where);
            if (ret != NI_OK) {
                ni_namelist_free(&nl);
                return ret;
            }

            /* update the namelist */  
            ni_namelist_delete(&nl, where);
            where = ni_namelist_match(nl, keys.ni_namelist_val[i]);
        }
    }
    ni_namelist_free(&nl);
    return NI_OK;
}
Ejemplo n.º 14
0
ni_status ni2_createdirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values)
{
    /* createprop given a directory rather than a pathname */

    ni_status ret;
    ni_property p;
    ni_namelist nl;
    ni_index where;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* fetch list of property keys from directory */
    NI_INIT(&nl);
    ret = ni_listprops(domain, dir, &nl);
    if (ret != NI_OK) {
        return ret;
    }

    /* check for existing property with this key */
    where = ni_namelist_match(nl, key);
    ni_namelist_free(&nl);

    /* if property doesn't exist, create it */
    if (where == NI_INDEX_NULL) {
        NI_INIT(&p);
        p.nip_name = ni_name_dup(key);
        p.nip_val = ni_namelist_dup(values);
        ret = ni_createprop(domain, dir, p, NI_INDEX_NULL);
        ni_prop_free(&p);
        return ret;
    }

    /* property exists: replace the existing values */
    ret = ni_writeprop(domain, dir, where, values);
    return ret;
}
Ejemplo n.º 15
0
ni_status ni2_create(void *domain, char *pathname)
{
    /* make a directory with the given pathname */
    /* do nothing if the directory already exists */

    ni_status ret;
    ni_id dir;

    /* need to be talking to the master */
    ni_needwrite(domain, 1);

    /* see if it already exists */
    ret = ni2_pathsearch(domain, &dir, pathname);
    if (ret == NI_OK) return NI_OK;

    /* doesn't exist: create it */
    ret = ni_root(domain, &dir);
    if (ret != NI_OK) return ret;

    if (pathname[0] == '/') ret = ni2_createpath(domain, &dir, pathname+1);
    else ret = ni2_createpath(domain, &dir, pathname);

    return ret; 
}
Ejemplo n.º 16
0
/*
 * Change a user's password in NetInfo.
 */
PAM_EXTERN
int 
pam_sm_chauthtok(pam_handle_t * pamh, int flags, int argc, const char **argv)
{
	char           *oldHash, *newHash;
	char           *oldPassword = NULL, *newPassword = NULL;
	void           *d;
	int             status, isroot, tries, maxTries;
	int		options = 0;
	int		amChangingExpiredPassword;
	ni_id           dir;
	ni_proplist     pl;
	ni_property     p;
	ni_namelist     nl;
	int             ni_uid, uid, secure, minlen, lifetime;
	ni_index        where;
	struct pam_conv *appconv;
	struct pam_message msg, *pmsg;
	struct pam_response *resp;
	const char     *cmiscptr = NULL;
	char           *uname;
	char            salt[9];
	int i;

	amChangingExpiredPassword = flags & PAM_CHANGE_EXPIRED_AUTHTOK;

	status = pam_get_item(pamh, PAM_CONV, (void **) &appconv);
	if (status != PAM_SUCCESS)
		return status;

	status = pam_get_item(pamh, PAM_USER, (void **) &uname);
	if (status != PAM_SUCCESS)
		return status;

	if (uname == NULL)
		return PAM_USER_UNKNOWN;

	status = pam_get_item(pamh, PAM_OLDAUTHTOK, (void **) &oldPassword);
	if (status != PAM_SUCCESS) {
		return status;
	}

	if (pam_test_option(&options, PAM_OPT_USE_FIRST_PASS, NULL) ||
	    pam_test_option(&options, PAM_OPT_TRY_FIRST_PASS, NULL))
	{
		if (pam_get_item(pamh, PAM_AUTHTOK, (void **) &newPassword) != PAM_SUCCESS)
			newPassword = NULL;

		if (pam_test_option(&options, PAM_OPT_USE_FIRST_PASS, NULL) && newPassword == NULL)
			return PAM_AUTHTOK_RECOVER_ERR;
	}
	d = domain_for_user(uname, NULL, &dir);
	if (d == (void *) NULL)
	{
		syslog(LOG_ERR, "user %s not found in NetInfo", uname);
		return PAM_USER_UNKNOWN;
	}

	/*
	 * These should be configurable in NetInfo.
	 */
	secure = secure_passwords();
	maxTries = secure ? 3 : 5;
	minlen = secure ? 8 : 5;

	/*
         * Read the passwd and uid from NetInfo.
         */
	status = ni_lookupprop(d, &dir, "passwd", &nl);
	if (status == NI_NOPROP)
		nl.ni_namelist_len = 0;
	else if (status != NI_OK)
	{
		ni_free(d);
		syslog(LOG_ERR, "NetInfo read failed: %s", ni_error(status));
		return netinfo2PamStatus(status);
	}
	oldHash = NULL;
	if (nl.ni_namelist_len > 0)
		oldHash = nl.ni_namelist_val[0];

	status = ni_lookupprop(d, &dir, "uid", &nl);
	if (status != NI_OK)
	{
		ni_free(d);
		syslog(LOG_ERR, "NetInfo read failed: %s", ni_error(status));
		return netinfo2PamStatus(status);
	}
	ni_uid = -2;
	if (nl.ni_namelist_len > 0)
		ni_uid = atoi(nl.ni_namelist_val[0]);

	/*
         * See if I'm uid 0 on the master host for the user's NetInfo domain.
         */
	isroot = is_root_on_master(d);
	uid = getuid();
	if (isroot)
	{
		if (flags & PAM_PRELIM_CHECK)
		{
			/* Don't need old password. */
			return PAM_SUCCESS;
		}
	}
	else if (uid != ni_uid)
	{
		ni_free(d);
		return PAM_PERM_DENIED;
	}

	if (flags & PAM_PRELIM_CHECK)
	{
		/*
		 * If we are not root, we should verify the old
		 * password.
		 */
		char           *encrypted;

		if (oldPassword != NULL &&
		   (pam_test_option(&options, PAM_OPT_USE_FIRST_PASS, NULL) ||
		    pam_test_option(&options, PAM_OPT_TRY_FIRST_PASS, NULL)))
		{
			encrypted = crypt(oldPassword, oldHash);

			if (oldPassword[0] == '\0' && oldHash != '\0')
				encrypted = ":";
			status = strcmp(encrypted, oldHash) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR;
			if (status != PAM_SUCCESS)
			{
				if (pam_test_option(&options, PAM_OPT_USE_FIRST_PASS, NULL))
					sendConversationMessage(appconv, "NetInfo password incorrect", PAM_ERROR_MSG, &options);
				else
					sendConversationMessage(appconv, "NetInfo password incorrect: try again", PAM_ERROR_MSG, &options);
			}
			else
			{
				ni_free(d);
				return PAM_SUCCESS;
			}
		}
		tries = 0;

		while (oldPassword == NULL && tries++ < maxTries)
		{
			pmsg = &msg;
			msg.msg_style = PAM_PROMPT_ECHO_OFF;
			msg.msg = OLD_PASSWORD_PROMPT;
			resp = NULL;

			status = appconv->conv(1, (struct pam_message **) & pmsg, &resp, appconv->appdata_ptr);
			if (status != PAM_SUCCESS)
			{
				ni_free(d);
				return status;
			}
			oldPassword = resp->resp;
			free(resp);

			encrypted = crypt(oldPassword, oldHash);

			if (oldPassword[0] == '\0' && oldHash != '\0')
				encrypted = ":";

			status = strcmp(encrypted, oldHash) == 0 ? PAM_SUCCESS : PAM_AUTH_ERR;

			if (status != PAM_SUCCESS)
			{
				int             abortMe = 0;

				if (oldPassword != NULL && oldPassword[0] == '\0')
					abortMe = 1;

				_pam_overwrite(oldPassword);
				_pam_drop(oldPassword);

				if (!amChangingExpiredPassword & abortMe)
				{
					sendConversationMessage(appconv, "Password change aborted", PAM_ERROR_MSG, &options);
					ni_free(d);
					return PAM_AUTHTOK_RECOVER_ERR;
				}
				else
				{
					sendConversationMessage(appconv, "NetInfo password incorrect: try again", PAM_ERROR_MSG, &options);
				}
			}
		}

		if (oldPassword == NULL)
		{
			status = PAM_MAXTRIES;
		}
		(void) pam_set_item(pamh, PAM_OLDAUTHTOK, oldPassword);
		ni_free(d);

		return status;
	}			/* PAM_PRELIM_CHECK */

	status = PAM_ABORT;
	tries = 0;

	while (newPassword == NULL && tries++ < maxTries)
	{
		pmsg = &msg;
		msg.msg_style = PAM_PROMPT_ECHO_OFF;
		msg.msg = NEW_PASSWORD_PROMPT;
		resp = NULL;

		status = appconv->conv(1, &pmsg, &resp, appconv->appdata_ptr);
		if (status != PAM_SUCCESS)
		{
			ni_free(d);
			return status;
		}
		newPassword = resp->resp;
		free(resp);

		if (newPassword[0] == '\0')
		{
			free(newPassword);
			newPassword = NULL;
		}

		if (newPassword != NULL)
		{
			if (isroot == 0)
			{
				if (oldPassword != NULL && !strcmp(oldPassword, newPassword))
				{
					cmiscptr = "Passwords must differ";
					newPassword = NULL;
				}
				else if (strlen(newPassword) < minlen)
				{
					cmiscptr = "Password too short";
					newPassword = NULL;
				}
			}
		} else
		{
			ni_free(d);
			return PAM_AUTHTOK_RECOVER_ERR;
		}

		if (cmiscptr == NULL)
		{
			/* get password again */
			char           *miscptr;

			pmsg = &msg;
			msg.msg_style = PAM_PROMPT_ECHO_OFF;
			msg.msg = AGAIN_PASSWORD_PROMPT;
			resp = NULL;

			status = appconv->conv(1, &pmsg, &resp, appconv->appdata_ptr);

			if (status != PAM_SUCCESS)
			{
				ni_free(d);
				return status;
			}
			miscptr = resp->resp;
			free(resp);

			if (miscptr[0] == '\0')
			{
				free(miscptr);
				miscptr = NULL;
			}
			if (miscptr == NULL)
			{
				if (!amChangingExpiredPassword)
				{
					sendConversationMessage(appconv, "Password change aborted",
						    PAM_ERROR_MSG, &options);
					ni_free(d);
					return PAM_AUTHTOK_RECOVER_ERR;
				}
			}
			else if (!strcmp(newPassword, miscptr))
			{
				miscptr = NULL;
				break;
			}
			sendConversationMessage(appconv, "You must enter the same password",
						PAM_ERROR_MSG, &options);
			miscptr = NULL;
			newPassword = NULL;
		}
		else
		{
			sendConversationMessage(appconv, cmiscptr, PAM_ERROR_MSG, &options);
			cmiscptr = NULL;
			newPassword = NULL;
		}
	}

	if (cmiscptr != NULL || newPassword == NULL)
	{
		ni_free(d);
		return PAM_MAXTRIES;
	}
	/*
         * Lock onto the master server.
         */
	ni_needwrite(d, 1);

	/*
         * Authenticate if necessary
         */
	if (isroot == 0)
	{
		ni_setuser(d, uname);
		ni_setpassword(d, oldPassword);
	}
	/*
        * Create a random salt
        */
	srandom((int) time((time_t *) NULL));
	salt[0] = saltchars[random() % strlen(saltchars)];
	salt[1] = saltchars[random() % strlen(saltchars)];
	salt[2] = '\0';
	newHash = crypt(newPassword, salt);

	/*
         * Change the password in NetInfo.
         */
	status = ni_read(d, &dir, &pl);
	if (status != NI_OK)
	{
		ni_free(d);
		syslog(LOG_ERR, "NetInfo read failed: %s", ni_error(status));
		return netinfo2PamStatus(status);
	}
	p.nip_name = "passwd";
	p.nip_val.ni_namelist_len = 1;
	p.nip_val.ni_namelist_val = (ni_name *) malloc(sizeof(ni_name));
	p.nip_val.ni_namelist_val[0] = newHash;

	where = ni_proplist_match(pl, p.nip_name, NULL);
	if (where == NI_INDEX_NULL)
		status = ni_createprop(d, &dir, p, NI_INDEX_NULL);
	else
		status = ni_writeprop(d, &dir, where, p.nip_val);

	if (status != NI_OK)
	{
		ni_free(d);
		syslog(LOG_ERR, "NetInfo write property \"passwd\" failed: %s", ni_error(status));
		return netinfo2PamStatus(status);
	}

	/*
	 * Now, update "change" property. If this fails, we've still
	 * updated the password... perhaps the user should be alerted
	 * of this.
	 */
	lifetime = password_lifetime();
	if (lifetime > 0)
	{
		struct timeval tp;
		char change[64];

		where = ni_proplist_match(pl, "change", NULL);

		gettimeofday(&tp, NULL);
		tp.tv_sec += lifetime;

		snprintf(change, sizeof(change), "%ld", tp.tv_sec);

		p.nip_name = "change";
		p.nip_val.ni_namelist_len = 1;
		p.nip_val.ni_namelist_val[0] = change;

		if (where == NI_INDEX_NULL)
			status = ni_createprop(d, &dir, p, NI_INDEX_NULL);
		else
			status = ni_writeprop(d, &dir, where, p.nip_val);

		if (status != NI_OK)
		{
			ni_free(d);
			syslog(LOG_ERR, "NetInfo write property \"change\" failed: %s", ni_error(status));
			return netinfo2PamStatus(status);
		}
	}

	free(p.nip_val.ni_namelist_val);

	ni_free(d);

	/* tell lookupd to invalidate its cache */
	{
		int i, proc = -1;
		unit lookup_buf[MAX_INLINE_UNITS];
#ifdef __NeXT__
		port_t port;
#else
		mach_port_t port;
#endif

		port = _lookupd_port(0);
		(void) _lookup_link(port, "_invalidatecache", &proc);
		(void) _lookup_one(port, proc, NULL, 0, lookup_buf, &i);
	}

	return PAM_SUCCESS;
}