static struct hostent * _yp_gethostnamadr(int type, const void *data) { static char *domain = NULL; struct hostent *h = NULL; const char *name; char buf[MAXHOSTNAMELEN]; char *res = NULL; int r, len; if (!domain && _yp_check(&domain) == 0) { errno = 0; /* ignore yp_bind errors */ return (NULL); } if (type == ASR_GETHOSTBYNAME) { name = data; len = strlen(name); r = yp_match(domain, "hosts.byname", name, len, &res, &len); } else { if (inet_ntop(AF_INET, data, buf, sizeof buf) == NULL) return (NULL); len = strlen(buf); r = yp_match(domain, "hosts.byaddr", buf, len, &res, &len); } if (r == 0) { h = hostent_from_yp(AF_INET, res); } else { errno = 0; /* ignore error if not found */ } if (res) free(res); return (h); }
int main(int argc, char *argv[]) { #ifdef YP char *username; #endif struct rlimit rl; int c; rl.rlim_cur = 0; rl.rlim_max = 0; (void)setrlimit(RLIMIT_CORE, &rl); (void)setpriority(PRIO_PROCESS, 0, 0); openlog("login", LOG_ODELAY, LOG_AUTH); while ((c = getopt(argc, argv, "s:v:")) != -1) switch (c) { case 'v': break; case 's': /* service */ if (strcmp(optarg, "login") != 0) { syslog(LOG_ERR, "%s: invalid service", optarg); exit(1); } break; default: syslog(LOG_ERR, "usage error"); exit(1); } switch (argc - optind) { case 2: /* class is not used */ case 1: #ifdef YP username = argv[optind]; #endif break; default: syslog(LOG_ERR, "usage error"); exit(1); } #ifdef YP if (_yp_check(NULL)) yp_chpass(username); #endif local_chpass(argv); /* NOTREACHED */ exit(0); }
/* * See if there's a master.passwd map. */ static int __has_ypmaster(void) { int keylen, resultlen; char *key, *result; static int checked = -1; static uid_t saved_uid, saved_euid; uid_t uid = getuid(), euid = geteuid(); /* * Do not recheck IFF the saved UID and the saved * EUID are the same. In all other cases, recheck. */ if (checked != -1 && saved_uid == uid && saved_euid == euid) return (checked); if (euid != 0) { saved_uid = uid; saved_euid = euid; checked = 0; return (checked); } if (!__ypdomain) { if (_yp_check(&__ypdomain) == 0) { saved_uid = uid; saved_euid = euid; checked = 0; return (checked); /* No domain. */ } } if (yp_first(__ypdomain, "master.passwd.byname", &key, &keylen, &result, &resultlen)) { saved_uid = uid; saved_euid = euid; checked = 0; return (checked); } free(result); if (key) free(key); saved_uid = uid; saved_euid = euid; checked = 1; return (checked); }
int main(int argc, char *argv[]) { struct passwd *pw = NULL, *opw = NULL, lpw; int i, ch, pfd, tfd, dfd; char *tz, *arg = NULL; sigset_t fullset; #ifdef YP use_yp = _yp_check(NULL); #endif /* We need to use the system timezone for date conversions. */ if ((tz = getenv("TZ")) != NULL) { unsetenv("TZ"); tzset(); setenv("TZ", tz, 1); } op = EDITENTRY; while ((ch = getopt(argc, argv, "a:s:ly")) != -1) switch(ch) { case 'a': op = LOADENTRY; arg = optarg; break; case 's': op = NEWSH; arg = optarg; break; #ifdef YP case 'l': use_yp = 0; break; case 'y': if (!use_yp) { warnx("YP not in use."); usage(); } force_yp = 1; break; #endif case '?': default: usage(); } argc -= optind; argv += optind; #ifdef YP if (op == LOADENTRY && use_yp) errx(1, "cannot load using YP, use -l to load local."); #endif uid = getuid(); if (op == EDITENTRY || op == NEWSH) switch(argc) { case 0: pw = getpwuid(uid); #ifdef YP if (pw && !force_yp) use_yp = 0; else if (use_yp) pw = ypgetpwuid(uid); #endif /* YP */ if (!pw) errx(1, "unknown user: uid %u", uid); break; case 1: pw = getpwnam(*argv); #ifdef YP if (pw && !force_yp) use_yp = 0; else if (use_yp) pw = ypgetpwnam(*argv); #endif /* YP */ if (!pw) errx(1, "unknown user: %s", *argv); if (uid && uid != pw->pw_uid) baduser(); break; default: usage(); } if (op == LOADENTRY) { if (argc != 0) errx(1, "option -a does not accept user argument"); if (uid) baduser(); pw = &lpw; if (!pw_scan(arg, pw, NULL)) exit(1); opw = getpwnam(pw->pw_name); } if (opw == NULL && (opw = pw_dup(pw)) == NULL) err(1, NULL); /* Edit the user passwd information if requested. */ if (op == EDITENTRY) { char tempname[] = _PATH_VARTMP "pw.XXXXXXXXXX"; int edit_status; if ((pw = pw_dup(pw)) == NULL) pw_error(NULL, 1, 1); dfd = mkstemp(tempname); if (dfd == -1 || fcntl(dfd, F_SETFD, 1) == -1) pw_error(tempname, 1, 1); display(tempname, dfd, pw); edit_status = edit(tempname, pw); close(dfd); unlink(tempname); switch (edit_status) { case EDIT_OK: break; case EDIT_NOCHANGE: pw_error(NULL, 0, 0); break; case EDIT_ERROR: default: pw_error(tempname, 1, 1); break; } } if (op == NEWSH) { /* protect p_shell -- it thinks NULL is /bin/sh */ if (!arg[0]) usage(); if (p_shell(arg, pw, NULL)) pw_error(NULL, 0, 1); } /* Drop user's real uid and block all signals to avoid a DoS. */ setuid(0); sigfillset(&fullset); sigdelset(&fullset, SIGINT); sigprocmask(SIG_BLOCK, &fullset, NULL); /* Get the passwd lock file and open the passwd file for reading. */ pw_init(); for (i = 1; (tfd = pw_lock(0)) == -1; i++) { if (i == 4) (void)fputs("Attempting to lock password file, " "please wait or press ^C to abort", stderr); (void)signal(SIGINT, kbintr); if (i % 16 == 0) fputc('.', stderr); usleep(250000); (void)signal(SIGINT, SIG_IGN); } if (i >= 4) fputc('\n', stderr); pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); if (pfd == -1 || fcntl(pfd, F_SETFD, 1) == -1) pw_error(_PATH_MASTERPASSWD, 1, 1); #ifdef YP if (use_yp) { if (pw_yp(pw, uid)) pw_error(NULL, 0, 1); else { pw_abort(); exit(0); } } else #endif /* YP */ { /* Copy the passwd file to the lock file, updating pw. */ pw_copy(pfd, tfd, pw, opw); /* If username changed we need to rebuild the entire db. */ arg = !strcmp(opw->pw_name, pw->pw_name) ? pw->pw_name : NULL; /* Now finish the passwd file update. */ if (pw_mkdb(arg, 0) == -1) pw_error(NULL, 0, 1); } exit(0); }
int getservent_r(struct servent *se, struct servent_data *sed) { char *p; #ifdef __SYMBIAN32__ #ifdef __EPOC32__ // Is this a good limit - should we double that to allow for MBS? char services_path[256]; #endif #endif char *cp, **q, *endp; long l; #ifdef __SYMBIAN32__ long int num_service=0;//for getservent #endif #ifdef YP if (sed->yp_stepping && _getservent_yp(sed)) { p = sed->line; goto unpack; } tryagain: #endif #ifdef __SYMBIAN32__ #ifndef __EPOC32__ if (sed->fp == NULL && (sed->fp = fopen(_PATH_SERVICES, "r")) == NULL) { return -1; } #else if (sed->fp == NULL && (sed->fp = fopen(get_services_path(services_path), "r")) == NULL) { return -1; } #endif //__EPOC32__ #else if (sed->fp == NULL && (sed->fp = fopen(_PATH_SERVICES, "r")) == NULL) return (-1); #endif //__SYMBIAN32__ again: if ((p = fgets(sed->line, sizeof sed->line, sed->fp)) == NULL) return (-1); #ifdef YP if (*p == '+' && _yp_check(NULL)) { if (sed->yp_name != NULL) { if (!_getservbyname_yp(sed)) goto tryagain; } else if (sed->yp_port != 0) { if (!_getservbyport_yp(sed)) goto tryagain; } else if (!_getservent_yp(sed)) goto tryagain; } unpack: #endif if (*p == '#') goto again; // to strip both carriage return and line feed characters cp = strpbrk(p, "#\r\n"); if (cp != NULL) *cp = '\0'; se->s_name = p; p = strpbrk(p, " \t"); if (p == NULL) goto again; *p++ = '\0'; while (*p == ' ' || *p == '\t') p++; cp = strpbrk(p, ",/"); if (cp == NULL) goto again; *cp++ = '\0'; l = strtol(p, &endp, 10); if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX) goto again; se->s_port = htons((in_port_t)l); se->s_proto = cp; q = se->s_aliases = sed->aliases; #ifdef __SYMBIAN32__ num_service++; if(num_service<=num_line) goto again; #endif cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; while (cp && *cp) { if (*cp == ' ' || *cp == '\t') { cp++; continue; } if (q < &sed->aliases[_MAXALIASES - 1]) *q++ = cp; cp = strpbrk(cp, " \t"); if (cp != NULL) *cp++ = '\0'; } *q = NULL; return (0); }
int main(int argc, char **argv) { enum { NEWSH, LOADENTRY, EDITENTRY } op; struct passwd *pw, lpw, old_pw; int ch, dfd, pfd, tfd; #ifdef YP int yflag = 0; #endif char *arg, *username = NULL; #ifdef __GNUC__ pw = NULL; /* XXX gcc -Wuninitialized */ arg = NULL; #endif #ifdef YP use_yp = _yp_check(NULL); #endif op = EDITENTRY; while ((ch = getopt(argc, argv, "a:s:ly")) != -1) switch (ch) { case 'a': op = LOADENTRY; arg = optarg; break; case 's': op = NEWSH; arg = optarg; break; case 'l': use_yp = 0; break; case 'y': #ifdef YP if (!use_yp) errx(1, "YP not in use."); yflag = 1; #else errx(1, "YP support not compiled in."); #endif break; default: usage(); } argc -= optind; argv += optind; uid = getuid(); switch (argc) { case 0: /* nothing */ break; case 1: username = argv[0]; break; default: usage(); } #ifdef YP /* * We need to determine if we _really_ want to use YP. * If we defaulted to YP (i.e. were not given the -y flag), * and the master is not running rpc.yppasswdd, we check * to see if the user exists in the local passwd database. * If so, we use it, otherwise we error out. */ if (use_yp && yflag == 0) { if (check_yppasswdd()) { /* * We weren't able to contact rpc.yppasswdd. * Check to see if we're in the local * password database. If we are, use it. */ if (username != NULL) pw = getpwnam(username); else pw = getpwuid(uid); if (pw != NULL) use_yp = 0; else { warnx("master YP server not running yppasswd" " daemon."); errx(1, "Can't change password."); } } } #endif #ifdef YP if (use_yp) Pw_error = yppw_error; else #endif Pw_error = pw_error; #ifdef YP if (op == LOADENTRY && use_yp) errx(1, "cannot load entry using YP.\n" "\tUse the -l flag to load local."); #endif if (op == EDITENTRY || op == NEWSH) { if (username != NULL) { pw = getpwnam(username); if (pw == NULL) errx(1, "unknown user: %s", username); if (uid && uid != pw->pw_uid) baduser(); } else { pw = getpwuid(uid); if (pw == NULL) errx(1, "unknown user: uid %u", uid); } /* Make a copy for later verification */ old_pw = *pw; old_pw.pw_gecos = strdup(old_pw.pw_gecos); if (!old_pw.pw_gecos) { err(1, "strdup"); /*NOTREACHED*/ } } if (op == NEWSH) { /* protect p_shell -- it thinks NULL is /bin/sh */ if (!arg[0]) usage(); if (p_shell(arg, pw, NULL)) (*Pw_error)(NULL, 0, 1); } if (op == LOADENTRY) { if (uid) baduser(); pw = &lpw; if (!pw_scan(arg, pw, NULL)) exit(1); } /* Edit the user passwd information if requested. */ if (op == EDITENTRY) { struct stat sb; dfd = mkstemp(tempname); if (dfd < 0 || fcntl(dfd, F_SETFD, 1) < 0) (*Pw_error)(tempname, 1, 1); if (atexit(cleanup)) { cleanup(); errx(1, "couldn't register cleanup"); } if (stat(dirname(tempname), &sb) == -1) err(1, "couldn't stat `%s'", dirname(tempname)); if (!(sb.st_mode & S_ISTXT)) errx(1, "temporary directory `%s' is not sticky", dirname(tempname)); display(tempname, dfd, pw); edit(tempname, pw); } #ifdef YP if (use_yp) { if (pw_yp(pw, uid)) yppw_error(NULL, 0, 1); else exit(0); /* Will not exit from this if. */ } #endif /* YP */ /* * Get the passwd lock file and open the passwd file for * reading. */ pw_init(); tfd = pw_lock(0); if (tfd < 0) { if (errno != EEXIST) err(1, "%s", _PATH_MASTERPASSWD_LOCK); warnx("The passwd file is busy, waiting..."); tfd = pw_lock(10); if (tfd < 0) { if (errno != EEXIST) err(1, "%s", _PATH_MASTERPASSWD_LOCK); errx(1, "The passwd file is still busy, " "try again later."); } } if (fcntl(tfd, F_SETFD, 1) < 0) pw_error(_PATH_MASTERPASSWD_LOCK, 1, 1); pfd = open(_PATH_MASTERPASSWD, O_RDONLY, 0); if (pfd < 0 || fcntl(pfd, F_SETFD, 1) < 0) pw_error(_PATH_MASTERPASSWD, 1, 1); /* Copy the passwd file to the lock file, updating pw. */ pw_copy(pfd, tfd, pw, (op == LOADENTRY) ? NULL : &old_pw); close(pfd); close(tfd); /* Now finish the passwd file update. */ if (pw_mkdb(username, 0) < 0) pw_error(NULL, 0, 1); exit(0); }
void pwyp_process(const char *username, int argc, char **argv) { char *master; int ch, r, rpcport, status; enum clnt_stat yr; struct yppasswd ypp; struct passwd pwb, pwb2, *pw; char pwbuf[1024]; struct timeval tv; CLIENT *client; while ((ch = getopt(argc, argv, "y")) != -1) { switch (ch) { case 'y': /* * Abosrb the -y that may have gotten us here. */ break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; switch (argc) { case 0: /* username already provided */ break; case 1: username = argv[0]; break; default: usage(); /*NOTREACHED*/ } if (_yp_check(NULL) == 0) { /* can't use YP. */ errx(EXIT_FAILURE, "NIS not in use."); } uid = getuid(); /* * Get local domain */ if ((r = yp_get_default_domain(&domain)) != 0) errx(EXIT_FAILURE, "Can't get local NIS domain (%s)", yperr_string(r)); /* * Find the host for the passwd map; it should be running * the daemon. */ if ((r = yp_master(domain, "passwd.byname", &master)) != 0) errx(EXIT_FAILURE, "Can't find the master NIS server (%s)", yperr_string(r)); /* * Ask the portmapper for the port of the daemon. */ if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) errx(EXIT_FAILURE, "Master NIS server not running yppasswd " "daemon"); /* * Be sure the port is privileged */ if (rpcport >= IPPORT_RESERVED) errx(EXIT_FAILURE, "Yppasswd daemon is on an invalid port"); /* Bail out if this is a local (non-yp) user, */ /* then get user's login identity */ if (!ypgetpwnam(username, &pwb) || getpwnam_r(username, &pwb2, pwbuf, sizeof(pwbuf), &pw) || pw == NULL) errx(EXIT_FAILURE, "NIS unknown user %s", username); if (uid && uid != pwb.pw_uid) { errno = EACCES; err(EXIT_FAILURE, "You may only change your own password"); } makeypp(&ypp, &pwb); client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp"); if (client == NULL) errx(EXIT_FAILURE, "Cannot contact yppasswdd on %s (%s)", master, yperr_string(YPERR_YPBIND)); client->cl_auth = authunix_create_default(); tv.tv_sec = 2; tv.tv_usec = 0; yr = clnt_call(client, YPPASSWDPROC_UPDATE, xdr_yppasswd, &ypp, xdr_int, &status, tv); if (yr != RPC_SUCCESS) errx(EXIT_FAILURE, "RPC to yppasswdd failed (%s)", clnt_sperrno(yr)); else if (status) printf("Couldn't change NIS password.\n"); else printf("The NIS password has been changed on %s, %s\n", master, "the master NIS passwd server."); }
static int getaddrinfo_async_run(struct asr_query *as, struct asr_result *ar) { #ifdef YP static char *domain = NULL; char *res; int len; char *name; #endif char fqdn[MAXDNAME]; const char *str; struct addrinfo *ai; int i, family, r; FILE *f; union { struct sockaddr sa; struct sockaddr_in sain; struct sockaddr_in6 sain6; } sa; next: switch (as->as_state) { case ASR_STATE_INIT: /* * First, make sure the parameters are valid. */ as->as_count = 0; if (as->as.ai.hostname == NULL && as->as.ai.servname == NULL) { ar->ar_gai_errno = EAI_NONAME; async_set_state(as, ASR_STATE_HALT); break; } if (as->as.ai.hostname && as->as.ai.hostname[0] == '\0') { ar->ar_gai_errno = EAI_NODATA; async_set_state(as, ASR_STATE_HALT); break; } ai = &as->as.ai.hints; if (ai->ai_addrlen || ai->ai_canonname || ai->ai_addr || ai->ai_next) { ar->ar_gai_errno = EAI_BADHINTS; async_set_state(as, ASR_STATE_HALT); break; } if (ai->ai_flags & ~AI_MASK || (ai->ai_flags & AI_CANONNAME && ai->ai_flags & AI_FQDN)) { ar->ar_gai_errno = EAI_BADFLAGS; async_set_state(as, ASR_STATE_HALT); break; } if (ai->ai_family != PF_UNSPEC && ai->ai_family != PF_INET && ai->ai_family != PF_INET6) { ar->ar_gai_errno = EAI_FAMILY; async_set_state(as, ASR_STATE_HALT); break; } if (ai->ai_socktype && ai->ai_socktype != SOCK_DGRAM && ai->ai_socktype != SOCK_STREAM && ai->ai_socktype != SOCK_RAW) { ar->ar_gai_errno = EAI_SOCKTYPE; async_set_state(as, ASR_STATE_HALT); break; } if (ai->ai_socktype == SOCK_RAW && get_port(as->as.ai.servname, NULL, 1) != 0) { ar->ar_gai_errno = EAI_SERVICE; async_set_state(as, ASR_STATE_HALT); break; } /* Restrict result set to configured address families */ if (ai->ai_flags & AI_ADDRCONFIG) { if (addrconfig_setup(as) != 0) { ar->ar_gai_errno = EAI_FAIL; async_set_state(as, ASR_STATE_HALT); break; } } /* Make sure there is at least a valid combination */ for (i = 0; matches[i].family != -1; i++) if (MATCH_FAMILY(ai->ai_family, i) && MATCH_SOCKTYPE(ai->ai_socktype, i) && MATCH_PROTO(ai->ai_protocol, i)) break; if (matches[i].family == -1) { ar->ar_gai_errno = EAI_BADHINTS; async_set_state(as, ASR_STATE_HALT); break; } if (ai->ai_protocol == 0 || ai->ai_protocol == IPPROTO_UDP) as->as.ai.port_udp = get_port(as->as.ai.servname, "udp", as->as.ai.hints.ai_flags & AI_NUMERICSERV); if (ai->ai_protocol == 0 || ai->ai_protocol == IPPROTO_TCP) as->as.ai.port_tcp = get_port(as->as.ai.servname, "tcp", as->as.ai.hints.ai_flags & AI_NUMERICSERV); if (as->as.ai.port_tcp == -2 || as->as.ai.port_udp == -2 || (as->as.ai.port_tcp == -1 && as->as.ai.port_udp == -1) || (ai->ai_protocol && (as->as.ai.port_udp == -1 || as->as.ai.port_tcp == -1))) { ar->ar_gai_errno = EAI_SERVICE; async_set_state(as, ASR_STATE_HALT); break; } ar->ar_gai_errno = 0; /* If hostname is NULL, use local address */ if (as->as.ai.hostname == NULL) { for (family = iter_family(as, 1); family != -1; family = iter_family(as, 0)) { /* * We could use statically built sockaddrs for * those, rather than parsing over and over. */ if (family == PF_INET) str = (ai->ai_flags & AI_PASSIVE) ? \ "0.0.0.0" : "127.0.0.1"; else /* PF_INET6 */ str = (ai->ai_flags & AI_PASSIVE) ? \ "::" : "::1"; /* This can't fail */ asr_sockaddr_from_str(&sa.sa, family, str); if ((r = addrinfo_add(as, &sa.sa, NULL))) { ar->ar_gai_errno = r; break; } } if (ar->ar_gai_errno == 0 && as->as_count == 0) { ar->ar_gai_errno = EAI_NODATA; } async_set_state(as, ASR_STATE_HALT); break; } /* Try numeric addresses first */ for (family = iter_family(as, 1); family != -1; family = iter_family(as, 0)) { if (asr_sockaddr_from_str(&sa.sa, family, as->as.ai.hostname) == -1) continue; if ((r = addrinfo_add(as, &sa.sa, NULL))) ar->ar_gai_errno = r; break; } if (ar->ar_gai_errno || as->as_count) { async_set_state(as, ASR_STATE_HALT); break; } if (ai->ai_flags & AI_NUMERICHOST) { ar->ar_gai_errno = EAI_NONAME; async_set_state(as, ASR_STATE_HALT); break; } async_set_state(as, ASR_STATE_NEXT_DB); break; case ASR_STATE_NEXT_DB: if (asr_iter_db(as) == -1) { async_set_state(as, ASR_STATE_NOT_FOUND); break; } as->as_family_idx = 0; async_set_state(as, ASR_STATE_SAME_DB); break; case ASR_STATE_NEXT_FAMILY: as->as_family_idx += 1; if (as->as.ai.hints.ai_family != AF_UNSPEC || AS_FAMILY(as) == -1) { /* The family was specified, or we have tried all * families with this DB. */ if (as->as_count) { ar->ar_gai_errno = 0; async_set_state(as, ASR_STATE_HALT); } else async_set_state(as, ASR_STATE_NEXT_DOMAIN); break; } async_set_state(as, ASR_STATE_SAME_DB); break; case ASR_STATE_NEXT_DOMAIN: /* domain search is only for dns */ if (AS_DB(as) != ASR_DB_DNS) { async_set_state(as, ASR_STATE_NEXT_DB); break; } as->as_family_idx = 0; free(as->as.ai.fqdn); as->as.ai.fqdn = NULL; r = iter_domain(as, as->as.ai.hostname, fqdn, sizeof(fqdn)); if (r == -1) { async_set_state(as, ASR_STATE_NEXT_DB); break; } if (r == 0) { ar->ar_gai_errno = EAI_FAIL; async_set_state(as, ASR_STATE_HALT); break; } as->as.ai.fqdn = strdup(fqdn); if (as->as.ai.fqdn == NULL) { ar->ar_gai_errno = EAI_MEMORY; async_set_state(as, ASR_STATE_HALT); } async_set_state(as, ASR_STATE_SAME_DB); break; case ASR_STATE_SAME_DB: /* query the current DB again */ switch (AS_DB(as)) { case ASR_DB_DNS: if (as->as.ai.fqdn == NULL) { /* First try, initialize domain iteration */ as->as_dom_flags = 0; as->as_dom_step = DOM_INIT; async_set_state(as, ASR_STATE_NEXT_DOMAIN); break; } family = (as->as.ai.hints.ai_family == AF_UNSPEC) ? AS_FAMILY(as) : as->as.ai.hints.ai_family; if (family == AF_INET && as->as.ai.flags & ASYNC_NO_INET) { async_set_state(as, ASR_STATE_NEXT_FAMILY); break; } else if (family == AF_INET6 && as->as.ai.flags & ASYNC_NO_INET6) { async_set_state(as, ASR_STATE_NEXT_FAMILY); break; } as->as.ai.subq = res_query_async_ctx(as->as.ai.fqdn, C_IN, (family == AF_INET6) ? T_AAAA : T_A, as->as_ctx); if (as->as.ai.subq == NULL) { if (errno == ENOMEM) ar->ar_gai_errno = EAI_MEMORY; else ar->ar_gai_errno = EAI_FAIL; async_set_state(as, ASR_STATE_HALT); break; } async_set_state(as, ASR_STATE_SUBQUERY); break; case ASR_DB_FILE: f = fopen(_PATH_HOSTS, "re"); if (f == NULL) { async_set_state(as, ASR_STATE_NEXT_DB); break; } family = (as->as.ai.hints.ai_family == AF_UNSPEC) ? AS_FAMILY(as) : as->as.ai.hints.ai_family; r = addrinfo_from_file(as, family, f); if (r == -1) { if (errno == ENOMEM) ar->ar_gai_errno = EAI_MEMORY; else ar->ar_gai_errno = EAI_FAIL; async_set_state(as, ASR_STATE_HALT); } else async_set_state(as, ASR_STATE_NEXT_FAMILY); fclose(f); break; #ifdef YP case ASR_DB_YP: if (!domain && _yp_check(&domain) == 0) { async_set_state(as, ASR_STATE_NEXT_DB); break; } family = (as->as.ai.hints.ai_family == AF_UNSPEC) ? AS_FAMILY(as) : as->as.ai.hints.ai_family; name = as->as.ai.hostname; /* XXX * ipnodes.byname could also contain IPv4 address */ r = yp_match(domain, (family == AF_INET6) ? "ipnodes.byname" : "hosts.byname", name, strlen(name), &res, &len); if (r == 0) { r = addrinfo_from_yp(as, family, res); free(res); if (r == -1) { if (errno == ENOMEM) ar->ar_gai_errno = EAI_MEMORY; else ar->ar_gai_errno = EAI_FAIL; async_set_state(as, ASR_STATE_HALT); break; } } async_set_state(as, ASR_STATE_NEXT_FAMILY); break; #endif default: async_set_state(as, ASR_STATE_NEXT_DB); } break; case ASR_STATE_SUBQUERY: if ((r = asr_run(as->as.ai.subq, ar)) == ASYNC_COND) return (ASYNC_COND); as->as.ai.subq = NULL; if (ar->ar_datalen == -1) { async_set_state(as, ASR_STATE_NEXT_FAMILY); break; } r = addrinfo_from_pkt(as, ar->ar_data, ar->ar_datalen); if (r == -1) { if (errno == ENOMEM) ar->ar_gai_errno = EAI_MEMORY; else ar->ar_gai_errno = EAI_FAIL; async_set_state(as, ASR_STATE_HALT); } else async_set_state(as, ASR_STATE_NEXT_FAMILY); free(ar->ar_data); break; case ASR_STATE_NOT_FOUND: /* No result found. Maybe we can try again. */ if (as->as.ai.flags & ASYNC_AGAIN) ar->ar_gai_errno = EAI_AGAIN; else ar->ar_gai_errno = EAI_NODATA; async_set_state(as, ASR_STATE_HALT); break; case ASR_STATE_HALT: if (ar->ar_gai_errno == 0) { ar->ar_count = as->as_count; ar->ar_addrinfo = as->as.ai.aifirst; as->as.ai.aifirst = NULL; } else { ar->ar_count = 0; ar->ar_addrinfo = NULL; } return (ASYNC_DONE); default: ar->ar_errno = EOPNOTSUPP; ar->ar_gai_errno = EAI_SYSTEM; async_set_state(as, ASR_STATE_HALT); break; } goto next; }
int main(int argc, char *argv[]) { int ch; int ypxfr_force = 0; char *ypxfr_dest_domain = NULL; char *ypxfr_source_host = NULL; char *ypxfr_source_domain = NULL; char *ypxfr_local_domain = NULL; char *ypxfr_master = NULL; unsigned long ypxfr_order = -1, ypxfr_skew_check = -1; char *ypxfr_mapname = NULL; int ypxfr_args = 0; char ypxfr_temp_map[MAXPATHLEN + 2]; char tempmap[MAXPATHLEN + 2]; char buf[MAXPATHLEN + 2]; DBT key, data; int remoteport; int interdom = 0; int secure = 0; debug = 1; if (!isatty(fileno(stderr))) { openlog("ypxfr", LOG_PID, LOG_DAEMON); _rpcpmstart = 1; } if (argc < 2) usage(); while ((ch = getopt(argc, argv, "fcd:h:s:p:C:")) != -1) { int my_optind; switch (ch) { case 'f': ypxfr_force++; ypxfr_args++; break; case 'c': ypxfr_clear = 0; ypxfr_args++; break; case 'd': ypxfr_dest_domain = optarg; ypxfr_args += 2; break; case 'h': ypxfr_source_host = optarg; ypxfr_args += 2; break; case 's': ypxfr_source_domain = optarg; ypxfr_args += 2; break; case 'p': yp_dir = optarg; ypxfr_args += 2; break; case 'C': /* * Whoever decided that the -C flag should take * four arguments is a twit. */ my_optind = optind - 1; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("transaction ID not specified"); usage(); } ypxfr_resp.transid = atol(argv[my_optind]); my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("RPC program number not specified"); usage(); } ypxfr_prognum = atol(argv[my_optind]); my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("address not specified"); usage(); } if (!inet_aton(argv[my_optind], &ypxfr_callback_addr.sin_addr)) { yp_error("failed to convert '%s' to IP addr", argv[my_optind]); exit(1); } my_optind++; if (argv[my_optind] == NULL || !strlen(argv[my_optind])) { yp_error("port not specified"); usage(); } ypxfr_callback_addr.sin_port = htons((u_short)atoi(argv[my_optind])); ypxfr_args += 5; break; default: usage(); break; } } ypxfr_mapname = argv[ypxfr_args + 1]; if (ypxfr_mapname == NULL) { yp_error("no map name specified"); usage(); } /* Always the case. */ ypxfr_callback_addr.sin_family = AF_INET; /* Determine if local NIS client facilities are turned on. */ if (!yp_get_default_domain(&ypxfr_local_domain) && _yp_check(&ypxfr_local_domain)) ypxfr_use_yplib = 1; /* * If no destination domain is specified, assume that the * local default domain is to be used and try to obtain it. * Fails if NIS client facilities are turned off. */ if (ypxfr_dest_domain == NULL) { if (ypxfr_use_yplib) { yp_get_default_domain(&ypxfr_dest_domain); } else { yp_error("no destination domain specified and \ the local domain name isn't set"); ypxfr_exit(YPXFR_BADARGS,NULL); } } /* * If a source domain is not specified, assume it to * be the same as the destination domain. */ if (ypxfr_source_domain == NULL) { ypxfr_source_domain = ypxfr_dest_domain; } /* * If the source host is not specified, assume it to be the * master for the specified map. If local NIS client facilities * are turned on, we can figure this out using yp_master(). * If not, we have to see if a local copy of the map exists * and extract its YP_MASTER_NAME record. If _that_ fails, * we are stuck and must ask the user for more information. */ if (ypxfr_source_host == NULL) { if (!ypxfr_use_yplib) { /* * Double whammy: NIS isn't turned on and the user * didn't specify a source host. */ char *dptr; key.data = "YP_MASTER_NAME"; key.size = sizeof("YP_MASTER_NAME") - 1; if (yp_get_record(ypxfr_dest_domain, ypxfr_mapname, &key, &data, 1) != YP_TRUE) { yp_error("no source host specified"); ypxfr_exit(YPXFR_BADARGS,NULL); } dptr = data.data; dptr[data.size] = '\0'; ypxfr_master = ypxfr_source_host = strdup(dptr); } } else { if (ypxfr_use_yplib) ypxfr_use_yplib = 0; } if (ypxfr_master == NULL) { if ((ypxfr_master = ypxfr_get_master(ypxfr_source_domain, ypxfr_mapname, ypxfr_source_host, ypxfr_use_yplib)) == NULL) { yp_error("failed to find master of %s in domain %s: %s", ypxfr_mapname, ypxfr_source_domain, ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_MADDR,NULL); } } /* * If we got here and ypxfr_source_host is still undefined, * it means we had to resort to using yp_master() to find the * master server for the map. The source host and master should * be identical. */ if (ypxfr_source_host == NULL) ypxfr_source_host = ypxfr_master; /* * Don't talk to ypservs on unprivileged ports. */ remoteport = getrpcport(ypxfr_source_host, YPPROG, YPVERS, IPPROTO_UDP); if (remoteport >= IPPORT_RESERVED) { yp_error("ypserv on %s not running on reserved port", ypxfr_source_host); ypxfr_exit(YPXFR_REFUSED, NULL); } if ((ypxfr_order = ypxfr_get_order(ypxfr_source_domain, ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", ypxfr_mapname, yp_errno == YP_TRUE ? "map has order 0" : ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_YPERR,NULL); } if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname, "YP_INTERDOMAIN", sizeof("YP_INTERDOMAIN") - 1)) interdom++; if (ypxfr_match(ypxfr_master, ypxfr_source_domain, ypxfr_mapname, "YP_SECURE", sizeof("YP_SECURE") - 1)) secure++; key.data = "YP_LAST_MODIFIED"; key.size = sizeof("YP_LAST_MODIFIED") - 1; /* The order number is immaterial when the 'force' flag is set. */ if (!ypxfr_force) { int ignore = 0; if (yp_get_record(ypxfr_dest_domain,ypxfr_mapname,&key,&data,1) != YP_TRUE) { switch (yp_errno) { case YP_NOKEY: ypxfr_exit(YPXFR_FORCE,NULL); break; case YP_NOMAP: /* * If the map doesn't exist, we're * creating it. Ignore the error. */ ignore++; break; case YP_BADDB: default: ypxfr_exit(YPXFR_DBM,NULL); break; } } if (!ignore && ypxfr_order <= atoi(data.data)) ypxfr_exit(YPXFR_AGE, NULL); } /* Construct a temporary map file name */ snprintf(tempmap, sizeof(tempmap), "%s.%d",ypxfr_mapname, getpid()); snprintf(ypxfr_temp_map, sizeof(ypxfr_temp_map), "%s/%s/%s", yp_dir, ypxfr_dest_domain, tempmap); if ((remoteport = getrpcport(ypxfr_source_host, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, IPPROTO_TCP))) { /* Don't talk to rpc.ypxfrds on unprovileged ports. */ if (remoteport >= IPPORT_RESERVED) { yp_error("rpc.ypxfrd on %s not using privileged port", ypxfr_source_host); ypxfr_exit(YPXFR_REFUSED, NULL); } /* Try to send using ypxfrd. If it fails, use old method. */ if (!ypxfrd_get_map(ypxfr_source_host, ypxfr_mapname, ypxfr_source_domain, ypxfr_temp_map)) goto leave; } /* Open the temporary map read/write. */ if ((dbp = yp_open_db_rw(ypxfr_dest_domain, tempmap, 0)) == NULL) { yp_error("failed to open temporary map file"); ypxfr_exit(YPXFR_DBM,NULL); } /* * Fill in the keys we already know, such as the order number, * master name, input file name (we actually make up a bogus * name for that) and output file name. */ snprintf(buf, sizeof(buf), "%lu", ypxfr_order); data.data = buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write order number to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } key.data = "YP_MASTER_NAME"; key.size = sizeof("YP_MASTER_NAME") - 1; data.data = ypxfr_master; data.size = strlen(ypxfr_master); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write master name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } key.data = "YP_DOMAIN_NAME"; key.size = sizeof("YP_DOMAIN_NAME") - 1; data.data = ypxfr_dest_domain; data.size = strlen(ypxfr_dest_domain); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write domain name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } snprintf (buf, sizeof(buf), "%s:%s", ypxfr_source_host, ypxfr_mapname); key.data = "YP_INPUT_NAME"; key.size = sizeof("YP_INPUT_NAME") - 1; data.data = &buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write input name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, ypxfr_mapname); key.data = "YP_OUTPUT_NAME"; key.size = sizeof("YP_OUTPUT_NAME") - 1; data.data = &buf; data.size = strlen(buf); if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to write output name to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } if (interdom) { key.data = "YP_INTERDOMAIN"; key.size = sizeof("YP_INTERDOMAIN") - 1; data.data = ""; data.size = 0; if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to add interdomain flag to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } } if (secure) { key.data = "YP_SECURE"; key.size = sizeof("YP_SECURE") - 1; data.data = ""; data.size = 0; if (yp_put_record(dbp, &key, &data, 0) != YP_TRUE) { yp_error("failed to add secure flag to database"); ypxfr_exit(YPXFR_DBM,ypxfr_temp_map); } } /* Now suck over the contents of the map from the master. */ if (ypxfr_get_map(ypxfr_mapname,ypxfr_source_domain, ypxfr_source_host, ypxfr_foreach)){ yp_error("failed to retrieve map from source host"); ypxfr_exit(YPXFR_YPERR,ypxfr_temp_map); } (void)(dbp->close)(dbp); dbp = NULL; /* <- yes, it seems this is necessary. */ leave: snprintf(buf, sizeof(buf), "%s/%s/%s", yp_dir, ypxfr_dest_domain, ypxfr_mapname); /* Peek at the order number again and check for skew. */ if ((ypxfr_skew_check = ypxfr_get_order(ypxfr_source_domain, ypxfr_mapname, ypxfr_master, 0)) == 0) { yp_error("failed to get order number of %s: %s", ypxfr_mapname, yp_errno == YP_TRUE ? "map has order 0" : ypxfrerr_string((ypxfrstat)yp_errno)); ypxfr_exit(YPXFR_YPERR,ypxfr_temp_map); } if (ypxfr_order != ypxfr_skew_check) ypxfr_exit(YPXFR_SKEW,ypxfr_temp_map); /* * Send a YPPROC_CLEAR to the local ypserv. */ if (ypxfr_clear) { char in = 0; char *out = NULL; int stat; if ((stat = callrpc("localhost",YPPROG,YPVERS,YPPROC_CLEAR, (xdrproc_t)xdr_void, (void *)&in, (xdrproc_t)xdr_void, (void *)out)) != RPC_SUCCESS) { yp_error("failed to send 'clear' to local ypserv: %s", clnt_sperrno((enum clnt_stat) stat)); ypxfr_exit(YPXFR_CLEAR, ypxfr_temp_map); } } /* * Put the new map in place immediately. I'm not sure if the * kernel does an unlink() and rename() atomically in the event * that we move a new copy of a map over the top of an existing * one, but there's less chance of a race condition happening * than if we were to do the unlink() ourselves. */ if (rename(ypxfr_temp_map, buf) == -1) { yp_error("rename(%s,%s) failed: %s", ypxfr_temp_map, buf, strerror(errno)); ypxfr_exit(YPXFR_FILE,NULL); } ypxfr_exit(YPXFR_SUCC,NULL); return(1); }
static struct passwd * __yppwlookup(int lookup, char *name, uid_t uid, struct passwd *pw, char *buf, size_t buflen, int *flagsp) { char bf[1 + _PW_NAME_LEN], *ypcurrent = NULL, *map = NULL; int yp_pw_flags = 0, ypcurrentlen, r, s = -1, pw_keynum; static long long yppbuf[_PW_BUF_LEN / sizeof(long long)]; struct _ypexclude *ypexhead = NULL; const char *host, *user, *dom; DBT key; for (pw_keynum = 1; pw_keynum; pw_keynum++) { bf[0] = _PW_KEYBYNUM; bcopy((char *)&pw_keynum, &bf[1], sizeof(pw_keynum)); key.data = (u_char *)bf; key.size = 1 + sizeof(pw_keynum); if (__hashpw(&key, buf, buflen, pw, flagsp) == 0) break; switch (pw->pw_name[0]) { case '+': if (!__ypdomain) { if (_yp_check(&__ypdomain) == 0) continue; } __ypproto_set(pw, yppbuf, *flagsp, &yp_pw_flags); if (!map) { if (lookup == LOOKUP_BYNAME) { map = PASSWD_BYNAME; name = strdup(name); } else { map = PASSWD_BYUID; asprintf(&name, "%u", uid); } } switch (pw->pw_name[1]) { case '\0': if (ypcurrent) { free(ypcurrent); ypcurrent = NULL; } r = yp_match(__ypdomain, map, name, strlen(name), &ypcurrent, &ypcurrentlen); if (r != 0 || ypcurrentlen > buflen) { if (ypcurrent) free(ypcurrent); ypcurrent = NULL; continue; } break; case '@': pwnam_netgrp: if (ypcurrent) { free(ypcurrent); ypcurrent = NULL; } if (s == -1) /* first time */ setnetgrent(pw->pw_name + 2); s = getnetgrent(&host, &user, &dom); if (s == 0) { /* end of group */ endnetgrent(); s = -1; continue; } else { if (user && *user) { r = yp_match(__ypdomain, map, user, strlen(user), &ypcurrent, &ypcurrentlen); } else goto pwnam_netgrp; if (r != 0 || ypcurrentlen > buflen) { if (ypcurrent) free(ypcurrent); ypcurrent = NULL; /* * just because this * user is bad, doesn't * mean they all are. */ goto pwnam_netgrp; } } break; default: if (ypcurrent) { free(ypcurrent); ypcurrent = NULL; } user = pw->pw_name + 1; r = yp_match(__ypdomain, map, user, strlen(user), &ypcurrent, &ypcurrentlen); if (r != 0 || ypcurrentlen > buflen) { if (ypcurrent) free(ypcurrent); ypcurrent = NULL; continue; } break; } bcopy(ypcurrent, buf, ypcurrentlen); buf[ypcurrentlen] = '\0'; if (__ypparse(pw, buf, yp_pw_flags) || __ypexclude_is(&ypexhead, pw->pw_name)) { if (s == 1) /* inside netgrp */ goto pwnam_netgrp; continue; } break; case '-': /* attempted exclusion */ switch (pw->pw_name[1]) { case '\0': break; case '@': setnetgrent(pw->pw_name + 2); while (getnetgrent(&host, &user, &dom)) { if (user && *user) __ypexclude_add(&ypexhead, user); } endnetgrent(); break; default: __ypexclude_add(&ypexhead, pw->pw_name + 1); break; } break; } if ((lookup == LOOKUP_BYUID && pw->pw_uid == uid) || (lookup == LOOKUP_BYNAME && strcmp(pw->pw_name, name) == 0)) goto done; if (s == 1) /* inside netgrp */ goto pwnam_netgrp; continue; } pw = NULL; done: __ypexclude_free(&ypexhead); __ypproto = NULL; if (ypcurrent) free(ypcurrent); ypcurrent = NULL; if (map) free(name); return (pw); }
struct passwd * getpwent(void) { #ifdef YP static char *name = NULL; char *map; #endif char bf[1 + sizeof(_pw_keynum)]; struct passwd *pw = NULL; DBT key; _THREAD_PRIVATE_MUTEX_LOCK(pw); if (!_pw_db && !__initdb()) goto done; #ifdef YP map = PASSWD_BYNAME; if (__getpwent_has_yppw == -1) __getpwent_has_yppw = __has_yppw(); again: if (__getpwent_has_yppw && (__ypmode != YPMODE_NONE)) { const char *user, *host, *dom; int keylen, datalen, r, s; char *key, *data = NULL; if (!__ypdomain) { if (_yp_check(&__ypdomain) == 0) { __ypmode = YPMODE_NONE; goto again; } } switch (__ypmode) { case YPMODE_FULL: if (__ypcurrent) { r = yp_next(__ypdomain, map, __ypcurrent, __ypcurrentlen, &key, &keylen, &data, &datalen); free(__ypcurrent); __ypcurrent = NULL; if (r != 0) { __ypmode = YPMODE_NONE; if (data) free(data); goto again; } __ypcurrent = key; __ypcurrentlen = keylen; } else { r = yp_first(__ypdomain, map, &__ypcurrent, &__ypcurrentlen, &data, &datalen); if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { __ypmode = YPMODE_NONE; if (data) free(data); goto again; } } bcopy(data, __ypline, datalen); free(data); break; case YPMODE_NETGRP: s = getnetgrent(&host, &user, &dom); if (s == 0) { /* end of group */ endnetgrent(); __ypmode = YPMODE_NONE; goto again; } if (user && *user) { r = yp_match(__ypdomain, map, user, strlen(user), &data, &datalen); } else goto again; if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { /* * if the netgroup is invalid, keep looking * as there may be valid users later on. */ if (data) free(data); goto again; } bcopy(data, __ypline, datalen); free(data); break; case YPMODE_USER: if (name) { r = yp_match(__ypdomain, map, name, strlen(name), &data, &datalen); __ypmode = YPMODE_NONE; free(name); name = NULL; if (r != 0 || __ypcurrentlen > sizeof(__ypline)) { if (data) free(data); goto again; } bcopy(data, __ypline, datalen); free(data); } else { /* XXX */ __ypmode = YPMODE_NONE; goto again; } break; case YPMODE_NONE: /* NOTREACHED */ break; } __ypline[datalen] = '\0'; if (__ypparse(&_pw_passwd, __ypline, __yp_pw_flags)) goto again; pw = &_pw_passwd; goto done; } #endif ++_pw_keynum; bf[0] = _PW_KEYBYNUM; bcopy((char *)&_pw_keynum, &bf[1], sizeof(_pw_keynum)); key.data = (u_char *)bf; key.size = 1 + sizeof(_pw_keynum); if (__hashpw(&key, _pw_string, sizeof _pw_string, &_pw_passwd, &_pw_flags)) { #ifdef YP static long long __yppbuf[_PW_BUF_LEN / sizeof(long long)]; const char *user, *host, *dom; /* if we don't have YP at all, don't bother. */ if (__getpwent_has_yppw) { if (_pw_passwd.pw_name[0] == '+') { /* set the mode */ switch (_pw_passwd.pw_name[1]) { case '\0': __ypmode = YPMODE_FULL; break; case '@': __ypmode = YPMODE_NETGRP; setnetgrent(_pw_passwd.pw_name + 2); break; default: __ypmode = YPMODE_USER; name = strdup(_pw_passwd.pw_name + 1); break; } __ypproto_set(&_pw_passwd, __yppbuf, _pw_flags, &__yp_pw_flags); goto again; } else if (_pw_passwd.pw_name[0] == '-') { /* an attempted exclusion */ switch (_pw_passwd.pw_name[1]) { case '\0': break; case '@': setnetgrent(_pw_passwd.pw_name + 2); while (getnetgrent(&host, &user, &dom)) { if (user && *user) __ypexclude_add(&__ypexhead, user); } endnetgrent(); break; default: __ypexclude_add(&__ypexhead, _pw_passwd.pw_name + 1); break; } goto again; } } #endif pw = &_pw_passwd; goto done; } done: _THREAD_PRIVATE_MUTEX_UNLOCK(pw); return (pw); }