int main(int argc, char *argv[]) { unsigned int lineno = 0; size_t linesize = 0; char *line = NULL; while (sudo_parseln(&line, &linesize, &lineno, stdin) != -1) printf("%6u\t%s\n", lineno, line); free(line); exit(0); }
/* * Read in /etc/nsswitch.conf * Returns a tail queue of matches. */ struct sudo_nss_list * sudo_read_nss(void) { FILE *fp; char *cp; int saw_files = FALSE; int saw_ldap = FALSE; int got_match = FALSE; static struct sudo_nss_list snl; if ((fp = fopen(_PATH_NSSWITCH_CONF, "r")) == NULL) goto nomatch; while ((cp = sudo_parseln(fp)) != NULL) { /* Skip blank or comment lines */ if (*cp == '\0') continue; /* Look for a line starting with "sudoers:" */ if (strncasecmp(cp, "sudoers:", 8) != 0) continue; /* Parse line */ for ((cp = strtok(cp + 8, " \t")); cp != NULL; (cp = strtok(NULL, " \t"))) { if (strcasecmp(cp, "files") == 0 && !saw_files) { tq_append(&snl, &sudo_nss_file); got_match = TRUE; } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) { tq_append(&snl, &sudo_nss_ldap); got_match = TRUE; } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) { /* NOTFOUND affects the most recent entry */ tq_last(&snl)->ret_if_notfound = TRUE; got_match = FALSE; } else got_match = FALSE; } /* Only parse the first "sudoers:" line */ break; } fclose(fp); nomatch: /* Default to files only if no matches */ if (tq_empty(&snl)) tq_append(&snl, &sudo_nss_file); return &snl; }
/* * Read in /etc/environment ala AIX and Linux. * Lines may be in either of three formats: * NAME=VALUE * NAME="VALUE" * NAME='VALUE' * with an optional "export" prefix so the shell can source the file. * Invalid lines, blank lines, or lines consisting solely of a comment * character are skipped. */ void read_env_file(const char *path, int overwrite) { FILE *fp; char *cp, *var, *val; size_t var_len, val_len; if ((fp = fopen(path, "r")) == NULL) return; while ((var = sudo_parseln(fp)) != NULL) { /* Skip blank or comment lines */ if (*var == '\0') continue; /* Skip optional "export " */ if (strncmp(var, "export", 6) == 0 && isspace((unsigned char) var[6])) { var += 7; while (isspace((unsigned char) *var)) { var++; } } /* Must be of the form name=["']value['"] */ for (val = var; *val != '\0' && *val != '='; val++) ; if (var == val || *val != '=') continue; var_len = (size_t)(val - var); val_len = strlen(++val); /* Strip leading and trailing single/double quotes */ if ((val[0] == '\'' || val[0] == '\"') && val[0] == val[val_len - 1]) { val[val_len - 1] = '\0'; val++; val_len -= 2; } cp = emalloc(var_len + 1 + val_len + 1); memcpy(cp, var, var_len + 1); /* includes '=' */ memcpy(cp + var_len + 1, val, val_len + 1); /* includes NUL */ sudo_putenv(cp, TRUE, overwrite); } fclose(fp); }
/* * Read in /etc/nsswitch.conf * Returns a tail queue of matches. */ struct sudo_nss_list * sudo_read_nss(void) { FILE *fp; char *cp, *line = NULL; size_t linesize = 0; #ifdef HAVE_SSSD bool saw_sss = false; #endif bool saw_files = false; bool saw_ldap = false; bool got_match = false; static struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl); debug_decl(sudo_read_nss, SUDO_DEBUG_NSS) if ((fp = fopen(_PATH_NSSWITCH_CONF, "r")) == NULL) goto nomatch; while (sudo_parseln(&line, &linesize, NULL, fp) != -1) { /* Skip blank or comment lines */ if (*line == '\0') continue; /* Look for a line starting with "sudoers:" */ if (strncasecmp(line, "sudoers:", 8) != 0) continue; /* Parse line */ for ((cp = strtok(line + 8, " \t")); cp != NULL; (cp = strtok(NULL, " \t"))) { if (strcasecmp(cp, "files") == 0 && !saw_files) { TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries); got_match = true; #ifdef HAVE_LDAP } else if (strcasecmp(cp, "ldap") == 0 && !saw_ldap) { TAILQ_INSERT_TAIL(&snl, &sudo_nss_ldap, entries); got_match = true; #endif #ifdef HAVE_SSSD } else if (strcasecmp(cp, "sss") == 0 && !saw_sss) { TAILQ_INSERT_TAIL(&snl, &sudo_nss_sss, entries); got_match = true; #endif } else if (strcasecmp(cp, "[NOTFOUND=return]") == 0 && got_match) { /* NOTFOUND affects the most recent entry */ TAILQ_LAST(&snl, sudo_nss_list)->ret_if_notfound = true; got_match = false; } else if (strcasecmp(cp, "[SUCCESS=return]") == 0 && got_match) { /* SUCCESS affects the most recent entry */ TAILQ_LAST(&snl, sudo_nss_list)->ret_if_found = true; got_match = false; } else got_match = false; } /* Only parse the first "sudoers:" line */ break; } free(line); fclose(fp); nomatch: /* Default to files only if no matches */ if (TAILQ_EMPTY(&snl)) TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries); debug_return_ptr(&snl); }
/* * Read in /etc/netsvc.conf (like nsswitch.conf on AIX) * Returns a tail queue of matches. */ struct sudo_nss_list * sudo_read_nss(void) { FILE *fp; char *cp, *ep, *line = NULL; size_t linesize = 0; #ifdef HAVE_SSSD bool saw_sss = false; #endif bool saw_files = false; bool saw_ldap = false; bool got_match = false; static struct sudo_nss_list snl = TAILQ_HEAD_INITIALIZER(snl); debug_decl(sudo_read_nss, SUDO_DEBUG_NSS) if ((fp = fopen(_PATH_NETSVC_CONF, "r")) == NULL) goto nomatch; while (sudo_parseln(&line, &linesize, NULL, fp) != -1) { /* Skip blank or comment lines */ if (*(cp = line) == '\0') continue; /* Look for a line starting with "sudoers = " */ if (strncasecmp(cp, "sudoers", 7) != 0) continue; cp += 7; while (isspace((unsigned char)*cp)) cp++; if (*cp++ != '=') continue; /* Parse line */ for ((cp = strtok(cp, ",")); cp != NULL; (cp = strtok(NULL, ","))) { /* Trim leading whitespace. */ while (isspace((unsigned char)*cp)) cp++; if (!saw_files && strncasecmp(cp, "files", 5) == 0 && (isspace((unsigned char)cp[5]) || cp[5] == '\0')) { TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries); got_match = true; ep = &cp[5]; #ifdef HAVE_LDAP } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 && (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { TAILQ_INSERT_TAIL(&snl, &sudo_nss_ldap, entries); got_match = true; ep = &cp[4]; #endif #ifdef HAVE_SSSD } else if (!saw_sss && strncasecmp(cp, "sss", 3) == 0 && (isspace((unsigned char)cp[3]) || cp[3] == '\0')) { TAILQ_INSERT_TAIL(&snl, &sudo_nss_sss, entries); got_match = true; ep = &cp[3]; #endif } else { got_match = false; } /* check for = auth qualifier */ if (got_match && *ep) { cp = ep; while (isspace((unsigned char)*cp) || *cp == '=') cp++; if (strncasecmp(cp, "auth", 4) == 0 && (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { TAILQ_LAST(&snl, sudo_nss_list)->ret_if_found = true; } } } /* Only parse the first "sudoers" line */ break; } fclose(fp); nomatch: /* Default to files only if no matches */ if (TAILQ_EMPTY(&snl)) TAILQ_INSERT_TAIL(&snl, &sudo_nss_file, entries); debug_return_ptr(&snl); }
/* * Read in /etc/netsvc.conf (like nsswitch.conf on AIX) * Returns a tail queue of matches. */ struct sudo_nss_list * sudo_read_nss(void) { FILE *fp; char *cp, *ep; int saw_files = FALSE; int saw_ldap = FALSE; int got_match = FALSE; static struct sudo_nss_list snl; if ((fp = fopen(_PATH_NETSVC_CONF, "r")) == NULL) goto nomatch; while ((cp = sudo_parseln(fp)) != NULL) { /* Skip blank or comment lines */ if (*cp == '\0') continue; /* Look for a line starting with "sudoers = " */ if (strncasecmp(cp, "sudoers", 7) != 0) continue; cp += 7; while (isspace((unsigned char)*cp)) cp++; if (*cp++ != '=') continue; /* Parse line */ for ((cp = strtok(cp, ",")); cp != NULL; (cp = strtok(NULL, ","))) { /* Trim leading whitespace. */ while (isspace((unsigned char)*cp)) cp++; if (!saw_files && strncasecmp(cp, "files", 5) == 0 && (isspace((unsigned char)cp[5]) || cp[5] == '\0')) { tq_append(&snl, &sudo_nss_file); got_match = TRUE; ep = &cp[5]; } else if (!saw_ldap && strncasecmp(cp, "ldap", 4) == 0 && (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { tq_append(&snl, &sudo_nss_ldap); got_match = TRUE; ep = &cp[4]; } else { got_match = FALSE; } /* check for = auth qualifier */ if (got_match && *ep) { cp = ep; while (isspace((unsigned char)*cp) || *cp == '=') cp++; if (strncasecmp(cp, "auth", 4) == 0 && (isspace((unsigned char)cp[4]) || cp[4] == '\0')) { tq_last(&snl)->ret_if_found = TRUE; } } } /* Only parse the first "sudoers" line */ break; } fclose(fp); nomatch: /* Default to files only if no matches */ if (tq_empty(&snl)) tq_append(&snl, &sudo_nss_file); return &snl; }
/* * Read in /etc/sudo.conf * Returns a list of plugins. */ static struct plugin_info_list * sudo_read_conf(const char *conf_file) { FILE *fp; char *cp, *name, *path; struct plugin_info *info; static struct plugin_info_list pil; /* XXX */ if ((fp = fopen(conf_file, "r")) == NULL) goto done; while ((cp = sudo_parseln(fp)) != NULL) { /* Skip blank or comment lines */ if (*cp == '\0') continue; /* Look for a line starting with "Path" */ if (strncasecmp(cp, "Path", 4) == 0) { /* Parse line */ if ((name = strtok(cp + 4, " \t")) == NULL || (path = strtok(NULL, " \t")) == NULL) { continue; } if (strcasecmp(name, "askpass") != 0) continue; askpass_path = estrdup(path); continue; } /* Look for a line starting with "Plugin" */ if (strncasecmp(cp, "Plugin", 6) == 0) { /* Parse line */ if ((name = strtok(cp + 6, " \t")) == NULL || (path = strtok(NULL, " \t")) == NULL) { continue; } info = emalloc(sizeof(*info)); info->symbol_name = estrdup(name); info->path = estrdup(path); info->prev = info; info->next = NULL; tq_append(&pil, info); continue; } } fclose(fp); done: if (tq_empty(&pil)) { /* Default policy plugin */ info = emalloc(sizeof(*info)); info->symbol_name = "sudoers_policy"; info->path = SUDOERS_PLUGIN; info->prev = info; info->next = NULL; tq_append(&pil, info); /* Default I/O plugin */ info = emalloc(sizeof(*info)); info->symbol_name = "sudoers_io"; info->path = SUDOERS_PLUGIN; info->prev = info; info->next = NULL; tq_append(&pil, info); } return &pil; }