/* * 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); }
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); }
/* * 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); }
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); }
/* * 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); }
/* * 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); }
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); }
/* * 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); }