示例#1
0
/*
 * name_to_int(rep)
 *
 * Translate the repository to a bitmask.
 * if we don't recognise the repository name, we return REP_ERANGE
 */
int
name_to_int(char *rep_name)
{
	int result = REP_ERANGE;

	if (strcmp(rep_name, "files") == 0)
		result = REP_FILES;
	else if (strcmp(rep_name, "nis") == 0)
		result = REP_NIS;
	else if (strcmp(rep_name, "ldap") == 0)
		result = REP_LDAP;
	else if (strcmp(rep_name, "compat") == 0) {
		struct __nsw_switchconfig *cfg;
		enum   __nsw_parse_err pserr;

		cfg = __nsw_getconfig("passwd_compat", &pserr);
		if (cfg == NULL) {
			result = REP_FILES | REP_NIS;
		} else {
			if (strcmp(cfg->lookups->service_name, "ldap") == 0)
				result = REP_FILES | REP_LDAP;
			else
				result = REP_ERANGE;
			(void) __nsw_freeconfig(cfg);
		}
	}

	return (result);
}
示例#2
0
char *
first_and_only_switch_policy(char *policy,
		    struct __nsw_switchconfig *default_conf,
		    char *head_msg)
{
	struct __nsw_switchconfig *conf;
	enum __nsw_parse_err perr;
	int policy_correct = 1;
	char *target_service = 0;
	int use_default = 0;

	if (default_conf == 0)
		default_conf = &publickey_default;

	conf = __nsw_getconfig(policy, &perr);
	if (no_switch_policy(conf)) {
		use_default = 1;
		conf = default_conf;
	}

	target_service = conf->lookups->service_name;

	if (conf->lookups->next != NULL) {
		policy_correct = 0;
		if (use_default) {
			(void) fprintf(stderr,
			"\n%s\n There is no publickey entry in %s.\n",
				head_msg, __NSW_CONFIG_FILE);
			(void) fprintf(stderr,
			"The default publickey policy is \"publickey: %s\".\n",
			switch_policy_str(default_conf));
		} else
			(void) fprintf(stderr,
		"\n%s\nThe publickey entry in %s is \"publickey: %s\".\n",
			head_msg, __NSW_CONFIG_FILE,
			switch_policy_str(conf));
	}

	if (policy_correct == 0)
		(void) fprintf(stderr,
	"I cannot figure out which publickey database you want to update.\n");
	if (!use_default && conf)
		__nsw_freeconfig(conf);

	if (policy_correct)
		return (target_service);
	else
		return (0);
}
示例#3
0
/*
 * Figure out which repository we use in compat mode.
 */
int
get_compat_mode(void)
{
	struct __nsw_switchconfig *cfg;
	enum   __nsw_parse_err pserr;
	int result = REP_COMPAT_NIS;

	if ((cfg = __nsw_getconfig("passwd_compat", &pserr)) != NULL) {
		if (strcmp(cfg->lookups->service_name, "ldap") == 0)
			result = REP_COMPAT_LDAP;
	}
	(void) __nsw_freeconfig(cfg);

	return (result);
}
示例#4
0
int
check_switch_policy(char *policy, char *target_service,
		    struct __nsw_switchconfig *default_conf,
		    char *head_msg, char *tail_msg)
{
	struct __nsw_switchconfig *conf;
	enum __nsw_parse_err perr;
	int policy_correct = 1;

	if (default_conf == 0)
		default_conf = &publickey_default;

	conf = __nsw_getconfig(policy, &perr);
	if (no_switch_policy(conf)) {
		if (!is_switch_policy(default_conf, target_service)) {
			(void) fprintf(stderr,
				"\n%s\nThere is no publickey entry in %s.\n",
				head_msg, __NSW_CONFIG_FILE);
			(void) fprintf(stderr,
			"The default publickey policy is \"publickey: %s\".\n",
			switch_policy_str(default_conf));
			policy_correct = 0;
		}
	} else if (!is_switch_policy(conf, target_service)) {
		(void) fprintf(stderr,
		"\n%s\nThe publickey entry in %s is \"publickey: %s\".\n",
			head_msg, __NSW_CONFIG_FILE,
			switch_policy_str(conf));
		policy_correct = 0;
	}
	/* should we exit ? */
	if (policy_correct == 0)
		(void) fprintf(stderr,
		"It should be \"publickey: %s\"%s\n\n",
			target_service, tail_msg);
	if (conf)
		__nsw_freeconfig(conf);

	return (policy_correct);
}
示例#5
0
/*
 * get_ns(rep, accesstype)
 *
 * returns a bitmask of repositories to use based on either
 *   1. the repository that is given as argument
 *   2. the nsswitch.conf file
 *   3. the type of access requested
 *
 * "accesstype" indicates whether we are reading from or writing to the
 * repository. We need to know this since "compat" will translate into
 * REP_NSS (the nss-switch) for READ access (needed to decode
 * the black-magic '+' entries) but it translates into a bitmask
 * on WRITE access.
 *
 * If we detect read-access in compat mode, we augment the result
 * with one of REP_COMPAT_{NIS,LDAP}. We need this in order to
 * implement ATTR_REP_NAME in nss_getpwnam.
 *
 * A return value of REP_NOREP indicates an error.
 */
int
get_ns(pwu_repository_t *rep, int accesstype)
{
	struct __nsw_switchconfig *conf = NULL;
	enum __nsw_parse_err pserr;
	struct __nsw_lookup *lkp;
	struct __nsw_lookup *lkp2;
	struct __nsw_lookup *lkp3;
	struct __nsw_lookup *lkpn;
	int result = REP_NOREP;

	if (rep != PWU_DEFAULT_REP) {
		result = name_to_int(rep->type);
		return (result);
	}

	conf = __nsw_getconfig("passwd", &pserr);
	if (conf == NULL) {
		/*
		 * No config found. The user didn't supply a repository,
		 * so we try to change the password in the default
		 * repositories (files and nis) even though we cannot
		 * find the name service switch entry. (Backward compat)
		 */
		syslog(LOG_ERR, "passwdutil.so: nameservice switch entry for "
		    "passwd not found.");
		result = REP_FILES | REP_NIS;
		return (result);
	}

	lkp = conf->lookups;

	/*
	 * Supported nsswitch.conf can have a maximum of 3 repositories.
	 * If we encounter an unsupported nsswitch.conf, we return REP_NSS
	 * to fall back to the nsswitch backend.
	 *
	 * Note that specifying 'ad' in the configuration is acceptable
	 * though changing AD users' passwords through passwd(1) is not.
	 * Therefore "ad" will be silently ignored.
	 */
	if (conf->num_lookups == 1) {
		/* files or compat */

		if (strcmp(lkp->service_name, "files") == 0) {
			result = name_to_int(lkp->service_name);
		} else if (strcmp(lkp->service_name, "compat") == 0) {
			if (accesstype == PWU_READ)
				result = REP_NSS | get_compat_mode();
			else
				result = name_to_int(lkp->service_name);
		} else
			result = REP_NSS;

	} else if (conf->num_lookups == 2) {
		lkp2 = lkp->next;
		if (strcmp(lkp->service_name, "files") == 0) {
			result = REP_FILES;
			if (strcmp(lkp2->service_name, "ldap") == 0)
				result |= REP_LDAP;
			else if (strcmp(lkp2->service_name, "nis") == 0)
				result |= REP_NIS;
			else if (strcmp(lkp2->service_name, "ad") != 0)
				result = REP_NSS;
			/* AD is ignored */
		} else {
			result = REP_NSS;
		}
	} else if (conf->num_lookups == 3) {
		/*
		 * Valid configurations with 3 repositories are:
		 *   files ad [nis | ldap ] OR
		 *   files [nis | ldap ] ad
		 */
		lkp2 = lkp->next;
		lkp3 = lkp2->next;
		if (strcmp(lkp2->service_name, "ad") == 0)
			lkpn = lkp3;
		else if (strcmp(lkp3->service_name, "ad") == 0)
			lkpn = lkp2;
		else
			lkpn = NULL;
		if (strcmp(lkp->service_name, "files") == 0 &&
		    lkpn != NULL) {
			result = REP_FILES;
			if (strcmp(lkpn->service_name, "ldap") == 0)
				result |= REP_LDAP;
			else if (strcmp(lkpn->service_name, "nis") == 0)
				result |= REP_NIS;
			else
				result = REP_NSS;
		} else {
			result = REP_NSS;
		}
	} else {
		result = REP_NSS;
	}

	(void) __nsw_freeconfig(conf);
	return (result);
}
示例#6
0
/*
 * Convert network-name into unix credential
 */
int
netname2user(const char netname[MAXNETNAMELEN + 1], uid_t *uidp, gid_t *gidp,
						int *gidlenp, gid_t *gidlist)
{
	struct __nsw_switchconfig *conf;
	struct __nsw_lookup *look;
	enum __nsw_parse_err perr;
	int needfree = 1, res;
	struct netid_userdata argp;
	int err;

	/*
	 * Take care of the special case of nobody. Compare the netname
	 * to the string "nobody". If they are equal, return the SVID
	 * standard value for nobody.
	 */

	if (strcmp(netname, "nobody") == 0) {
		*uidp = NOBODY_UID;
		*gidp = NOBODY_UID;
		*gidlenp = 0;
		return (1);
	}

	/*
	 * First we do some generic sanity checks on the name we were
	 * passed. This lets us assume they are correct in the backends.
	 *
	 * NOTE: this code only recognizes names of the form :
	 *		unix.UID@domainname
	 */
	if (strncmp(netname, OPSYS, OPSYS_LEN) != 0)
		return (0);
	if (!isdigit(netname[OPSYS_LEN+1]))	/* check for uid string */
		return (0);

	argp.uidp = uidp;
	argp.gidp = gidp;
	argp.gidlenp = gidlenp;
	argp.gidlist = gidlist;
	(void) mutex_lock(&serialize_netname_r);

	conf = __nsw_getconfig("publickey", &perr);
	if (!conf) {
		conf = &publickey_default;
		needfree = 0;
	} else
		needfree = 1; /* free the config structure */

	for (look = conf->lookups; look; look = look->next) {
		if (strcmp(look->service_name, "nis") == 0)
			res = netname2user_nis(&err, (char *)netname, &argp);
		else if (strcmp(look->service_name, "files") == 0)
			res = netname2user_files(&err, (char *)netname, &argp);
		else if (strcmp(look->service_name, "ldap") == 0)
			res = netname2user_ldap(&err, (char *)netname, &argp);
		else {
			syslog(LOG_INFO,
			    "netname2user: unknown nameservice for publickey"
			    "info '%s'\n", look->service_name);
			err = __NSW_UNAVAIL;
		}
		switch (look->actions[err]) {
			case __NSW_CONTINUE :
				break;
			case __NSW_RETURN :
				if (needfree)
					(void) __nsw_freeconfig(conf);
				(void) mutex_unlock(&serialize_netname_r);
				return (res);
			default :
				syslog(LOG_ERR,
				    "netname2user: Unknown action for "
				    "nameservice '%s'", look->service_name);
		}
	}
	if (needfree)
		(void) __nsw_freeconfig(conf);
	(void) mutex_unlock(&serialize_netname_r);
	return (0);
}
示例#7
0
int
prldap_x_install_dns_skipdb(LDAP *ld, const char *skip)
{
    enum __nsw_parse_err		pserr;
    struct __nsw_switchconfig       *conf;
    struct __nsw_lookup             *lkp;
    struct ldap_dns_fns             dns_fns;
    char                            *name_list = NULL;
    char                            *tmp;
    const char                      *name;
    int                             len;
    boolean_t                       got_skip = B_FALSE;

    /*
     * db_root_hosts.lock mutex is used to ensure that the name list
     * is not in use by the name service switch while we are updating
     * the host_service
     */

    (void) mutex_lock(&db_root_hosts.lock);
    conf = __nsw_getconfig("hosts", &pserr);
    if (conf == NULL) {
        (void) mutex_unlock(&db_root_hosts.lock);
        return (0);
    }

    /* check for skip and count other backends */
    for (lkp = conf->lookups; lkp != NULL; lkp = lkp->next) {
        name = lkp->service_name;
        if (strcmp(name, skip) == 0) {
            got_skip = B_TRUE;
            continue;
        }
        if (name_list == NULL)
            name_list = strdup(name);
        else {
            len = strlen(name_list);
            tmp = realloc(name_list, len + strlen(name) + 2);
            if (tmp == NULL) {
                free(name_list);
                name_list = NULL;
            } else {
                name_list = tmp;
                name_list[len++] = ' ';
                (void) strcpy(name_list+len, name);
            }
        }
        if (name_list == NULL) {        /* alloc error */
            (void) mutex_unlock(&db_root_hosts.lock);
            __nsw_freeconfig(conf);
            return (-1);
        }
    }
    __nsw_freeconfig(conf);
    if (!got_skip) {
        /*
         * Since skip name service not used for hosts, we do not need
         * to install our private address resolution function
         */
        (void) mutex_unlock(&db_root_hosts.lock);
        if (name_list != NULL)
            free(name_list);
        return (0);
    }
    if (host_service != NULL)
        free(host_service);
    host_service = name_list;
    (void) mutex_unlock(&db_root_hosts.lock);

    if (ldap_get_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
        return (-1);
    dns_fns.lddnsfn_bufsize = PR_NETDB_BUF_SIZE;
    dns_fns.lddnsfn_gethostbyname = prldap_gethostbyname1;
    if (ldap_set_option(ld, LDAP_OPT_DNS_FN_PTRS, &dns_fns) != 0)
        return (-1);
    return (0);
}
示例#8
0
/*
 * Convert unix cred to network-name
 *
 * It uses the publickey policy in the /etc/nsswitch.conf file
 * (Unless the netname is "nobody", which is special cased).
 * If there is no publickey policy in /etc/nsswitch.conf,
 * the default publickey policy is used, which is
 *	publickey: nis [NOTFOUND=return] files
 * Note that for the non-nisplus case, there is no failover
 * so only the first entry would be relevant for those cases.
 */
int
user2netname(char netname[MAXNETNAMELEN + 1], const uid_t uid,
							const char *domain)
{
	struct __nsw_switchconfig *conf;
	struct __nsw_lookup *look;
	int needfree = 1, res = 0;
	enum __nsw_parse_err perr;
	int err;

	/*
	 * Take care of the special case of "nobody". If the uid is
	 * the value assigned by the SVID for nobody, return the string
	 * "nobody".
	 */

	if (uid == NOBODY_UID) {
		(void) strlcpy(netname, "nobody", sizeof (netname));
		return (1);
	}

	netname[0] = '\0';  /* make null first (no need for memset) */

	if (mutex_lock(&serialize_netname) == EDEADLK) {
		/*
		 * This thread already holds this lock. This scenario
		 * occurs when a process requires a netname which
		 * itself requires a netname to look up. As we clearly
		 * can't continue like this we return 'nobody'.
		 */
		(void) strlcpy(netname, "nobody", sizeof (netname));
		return (1);
	}

	conf = __nsw_getconfig("publickey", &perr);
	if (!conf) {
		conf = &publickey_default;
		needfree = 0;
	}

	for (look = conf->lookups; look; look = look->next) {
		/* ldap, nis, and files all do the same thing. */
		if (strcmp(look->service_name, "ldap") == 0 ||
		    strcmp(look->service_name, "nis") == 0 ||
		    strcmp(look->service_name, "files") == 0)
			res = user2netname_nis(&err,
			    netname, uid, (char *)domain);
		else {
			syslog(LOG_INFO,
			    "user2netname: unknown nameservice \
					for publickey info '%s'\n",
			    look->service_name);
			err = __NSW_UNAVAIL;
		}
		switch (look->actions[err]) {
			case __NSW_CONTINUE :
				break;
			case __NSW_RETURN :
				if (needfree)
					(void) __nsw_freeconfig(conf);
				(void) mutex_unlock(&serialize_netname);
				return (res);
			default :
				syslog(LOG_ERR,
			"user2netname: Unknown action for nameservice '%s'",
				    look->service_name);
			}
	}
	if (needfree)
		(void) __nsw_freeconfig(conf);
	(void) mutex_unlock(&serialize_netname);
	return (0);
}