internal_function nss_parse_service_list (const char *line) { service_user *result = NULL, **nextp = &result; while (1) { service_user *new_service; const char *name; while (isspace (line[0])) ++line; if (line[0] == '\0') /* No source specified. */ return result; /* Read <source> identifier. */ name = line; while (line[0] != '\0' && !isspace (line[0]) && line[0] != '[') ++line; if (name == line) return result; new_service = (service_user *) malloc (sizeof (service_user) + (line - name + 1)); if (new_service == NULL) return result; *((char *) __mempcpy (new_service->name, name, line - name)) = '\0'; /* Set default actions. */ new_service->actions[2 + NSS_STATUS_TRYAGAIN] = NSS_ACTION_CONTINUE; new_service->actions[2 + NSS_STATUS_UNAVAIL] = NSS_ACTION_CONTINUE; new_service->actions[2 + NSS_STATUS_NOTFOUND] = NSS_ACTION_CONTINUE; new_service->actions[2 + NSS_STATUS_SUCCESS] = NSS_ACTION_RETURN; new_service->actions[2 + NSS_STATUS_RETURN] = NSS_ACTION_RETURN; new_service->library = NULL; new_service->known = NULL; new_service->next = NULL; while (isspace (line[0])) ++line; if (line[0] == '[') { /* Read criterions. */ do ++line; while (line[0] != '\0' && isspace (line[0])); do { int not; enum nss_status status; lookup_actions action; /* Grok ! before name to mean all statii but that one. */ not = line[0] == '!'; if (not) ++line; /* Read status name. */ name = line; while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' && line[0] != ']') ++line; /* Compare with known statii. */ if (line - name == 7) { if (__strncasecmp (name, "SUCCESS", 7) == 0) status = NSS_STATUS_SUCCESS; else if (__strncasecmp (name, "UNAVAIL", 7) == 0) status = NSS_STATUS_UNAVAIL; else return result; } else if (line - name == 8) { if (__strncasecmp (name, "NOTFOUND", 8) == 0) status = NSS_STATUS_NOTFOUND; else if (__strncasecmp (name, "TRYAGAIN", 8) == 0) status = NSS_STATUS_TRYAGAIN; else return result; } else return result; while (isspace (line[0])) ++line; if (line[0] != '=') return result; do ++line; while (isspace (line[0])); name = line; while (line[0] != '\0' && !isspace (line[0]) && line[0] != '=' && line[0] != ']') ++line; if (line - name == 6 && __strncasecmp (name, "RETURN", 6) == 0) action = NSS_ACTION_RETURN; else if (line - name == 8 && __strncasecmp (name, "CONTINUE", 8) == 0) action = NSS_ACTION_CONTINUE; else return result; if (not) { /* Save the current action setting for this status, set them all to the given action, and reset this one. */ const lookup_actions save = new_service->actions[2 + status]; new_service->actions[2 + NSS_STATUS_TRYAGAIN] = action; new_service->actions[2 + NSS_STATUS_UNAVAIL] = action; new_service->actions[2 + NSS_STATUS_NOTFOUND] = action; new_service->actions[2 + NSS_STATUS_SUCCESS] = action; new_service->actions[2 + status] = save; } else new_service->actions[2 + status] = action; /* Skip white spaces. */ while (isspace (line[0])) ++line; } while (line[0] != ']'); /* Skip the ']'. */ ++line; } *nextp = new_service; nextp = &new_service->next; } }
int ruserpass (const char *host, const char **aname, const char **apass) { char *hdir, *buf, *tmp; char myname[1024], *mydomain; int t, usedefault = 0; struct stat64 stb; hdir = __libc_secure_getenv("HOME"); if (hdir == NULL) { /* If we can't get HOME, fail instead of trying ".", which is no improvement. This really should call getpwuid(getuid()). */ /*hdir = ".";*/ return -1; } buf = alloca (strlen (hdir) + 8); __stpcpy (__stpcpy (buf, hdir), "/.netrc"); cfile = fopen(buf, "rce"); if (cfile == NULL) { if (errno != ENOENT) warn("%s", buf); return (0); } /* No threads use this stream. */ __fsetlocking (cfile, FSETLOCKING_BYCALLER); if (__gethostname(myname, sizeof(myname)) < 0) myname[0] = '\0'; mydomain = __strchrnul(myname, '.'); next: while ((t = token())) switch(t) { case DEFAULT: usedefault = 1; /* FALL THROUGH */ case MACHINE: if (!usedefault) { if (token() != ID) continue; /* * Allow match either for user's input host name * or official hostname. Also allow match of * incompletely-specified host in local domain. */ if (__strcasecmp(host, tokval) == 0) goto match; /* if (__strcasecmp(hostname, tokval) == 0) goto match; if ((tmp = strchr(hostname, '.')) != NULL && __strcasecmp(tmp, mydomain) == 0 && __strncasecmp(hostname, tokval, tmp-hostname) == 0 && tokval[tmp - hostname] == '\0') goto match; */ if ((tmp = strchr(host, '.')) != NULL && __strcasecmp(tmp, mydomain) == 0 && __strncasecmp(host, tokval, tmp - host) == 0 && tokval[tmp - host] == '\0') goto match; continue; } match: while ((t = token()) && t != MACHINE && t != DEFAULT) switch(t) { case LOGIN: if (token()) { if (*aname == 0) { char *newp; newp = malloc((unsigned) strlen(tokval) + 1); if (newp == NULL) { warnx(_("out of memory")); goto bad; } *aname = strcpy(newp, tokval); } else { if (strcmp(*aname, tokval)) goto next; } } break; case PASSWD: if (strcmp(*aname, "anonymous") && fstat64(fileno(cfile), &stb) >= 0 && (stb.st_mode & 077) != 0) { warnx(_("Error: .netrc file is readable by others.")); warnx(_("Remove password or make file unreadable by others.")); goto bad; } if (token() && *apass == 0) { char *newp; newp = malloc((unsigned) strlen(tokval) + 1); if (newp == NULL) { warnx(_("out of memory")); goto bad; } *apass = strcpy(newp, tokval); } break; case ACCOUNT: break; case MACDEF: break; default: warnx(_("Unknown .netrc keyword %s"), tokval); break; } goto done; } done: (void) fclose(cfile); return (0); bad: (void) fclose(cfile); return (-1); }