static void do_logfile(char *msg) { char *full_line; size_t len; mode_t oldmask; time_t now; FILE *fp; oldmask = umask(077); fp = fopen(def_logfile, "a"); (void) umask(oldmask); if (fp == NULL) { send_mail(_("unable to open log file: %s: %s"), def_logfile, strerror(errno)); } else if (!lock_file(fileno(fp), SUDO_LOCK)) { send_mail(_("unable to lock log file: %s: %s"), def_logfile, strerror(errno)); } else { #ifdef HAVE_SETLOCALE const char *old_locale = estrdup(setlocale(LC_ALL, NULL)); if (!setlocale(LC_ALL, def_sudoers_locale)) setlocale(LC_ALL, "C"); #endif /* HAVE_SETLOCALE */ now = time(NULL); if (def_loglinelen < sizeof(LOG_INDENT)) { /* Don't pretty-print long log file lines (hard to grep) */ if (def_log_host) (void) fprintf(fp, "%s : %s : HOST=%s : %s\n", get_timestr(now, def_log_year), user_name, user_shost, msg); else (void) fprintf(fp, "%s : %s : %s\n", get_timestr(now, def_log_year), user_name, msg); } else { if (def_log_host) len = easprintf(&full_line, "%s : %s : HOST=%s : %s", get_timestr(now, def_log_year), user_name, user_shost, msg); else len = easprintf(&full_line, "%s : %s : %s", get_timestr(now, def_log_year), user_name, msg); /* * Print out full_line with word wrap around def_loglinelen chars. */ writeln_wrap(fp, full_line, len, def_loglinelen); efree(full_line); } (void) fflush(fp); (void) lock_file(fileno(fp), SUDO_UNLOCK); (void) fclose(fp); #ifdef HAVE_SETLOCALE setlocale(LC_ALL, old_locale); efree((void *)old_locale); #endif /* HAVE_SETLOCALE */ } }
char * get_suggestions(sqlite3 *db, char *query) { char *retval = NULL; char *term; char *temp; char *sqlstr; int count; int rc; sqlite3_stmt *stmt; if ((term = strrchr(query, ' ')) == NULL) { term = query; query = NULL; } else { *term++ = 0; } char **list = edits1(term); int n = strlen(term); count = n + n -1 + 26 * n + 26 * (n + 1); char *termlist = build_termlist(list, count); easprintf(&sqlstr, "SELECT word FROM mandb_dict " "WHERE word IN %s ORDER BY frequency DESC LIMIT 10", termlist); rc = sqlite3_prepare_v2(db, sqlstr, -1, &stmt, NULL); if (rc != SQLITE_OK) { warnx("%s", sqlite3_errmsg(db)); return NULL; } easprintf(&temp, "{\n{ query:\'%s%s%s\',\n " "suggestions:[", query ? query : "", query ? " " : "", term); concat(&retval, temp); free(temp); count = 0; while (sqlite3_step(stmt) == SQLITE_ROW) { if (count++) concat(&retval, ","); easprintf(&temp, "\'%s %s\'\n", query ? query : "",sqlite3_column_text(stmt, 0)); concat(&retval, temp); free(temp); } concat(&retval, "]\n}"); sqlite3_finalize(stmt); free(sqlstr); free(termlist); free_list(list, count); return retval; }
/* * known_word-- * Pass an array of strings to this function and it will return the word with * maximum frequency in the dictionary. If no word in the array list is found * in the dictionary, it returns NULL * #TODO rename this function */ static char * known_word(sqlite3 *db, char **list, int n) { int i, rc; char *sqlstr; char *correct = NULL; sqlite3_stmt *stmt; char *termlist = build_termlist(list, n); easprintf(&sqlstr, "SELECT word FROM mandb_dict WHERE " "frequency = (SELECT MAX(frequency) FROM mandb_dict " "WHERE word IN %s) AND word IN %s", termlist, termlist); rc = sqlite3_prepare_v2(db, sqlstr, -1, &stmt, NULL); if (rc != SQLITE_OK) { warnx("%s", sqlite3_errmsg(db)); return NULL; } if (sqlite3_step(stmt) == SQLITE_ROW) correct = strdup((char *) sqlite3_column_text(stmt, 0)); sqlite3_finalize(stmt); free(sqlstr); free(termlist); return (correct); }
/* * underline a string, pager style. */ static char * ul_term(const char *s, const struct term_args *ta) { char *dst; easprintf(&dst, "%s%s%s", ta->smul, s, ta->rmul); return dst; }
static void sudo_debug_write_conv(const char *func, const char *file, int lineno, const char *str, int len, int errno_val) { struct sudo_conv_message msg; struct sudo_conv_reply repl; char *buf = NULL; /* Call conversation function */ if (sudo_conv != NULL) { /* Remove the newline at the end if appending extra info. */ if (str[len - 1] == '\n') len--; if (func != NULL && file != NULL && lineno != 0) { if (errno_val) { easprintf(&buf, "%.*s: %s @ %s() %s:%d", len, str, strerror(errno_val), func, file, lineno); } else { easprintf(&buf, "%.*s @ %s() %s:%d", len, str, func, file, lineno); } str = buf; } else if (errno_val) { easprintf(&buf, "%.*s: %s", len, str, strerror(errno_val)); str = buf; } memset(&msg, 0, sizeof(msg)); memset(&repl, 0, sizeof(repl)); msg.msg_type = SUDO_CONV_DEBUG_MSG; msg.msg = str; sudo_conv(1, &msg, &repl); if (buf != NULL) efree(buf); } }
int linux_audit_role_change(const char *old_context, const char *new_context, const char *ttyn) { int au_fd, rc; char *message; if ((au_fd = linux_audit_open()) == -1) return -1; /* audit role change using the same format as newrole(1) */ easprintf(&message, "newrole: old-context=%s new-context=%s", old_context, new_context); rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE, message, NULL, NULL, ttyn, 1); if (rc <= 0) warning("unable to send audit message"); efree(message); return rc; }
/* * run_query -- * Performs the searches for the keywords entered by the user. * The 2nd param: snippet_args is an array of strings providing values for the * last three parameters to the snippet function of sqlite. (Look at the docs). * The 3rd param: args contains rest of the search parameters. Look at * arpopos-utils.h for the description of individual fields. * */ int run_query(sqlite3 *db, const char *snippet_args[3], query_args *args) { const char *default_snippet_args[3]; char *section_clause = NULL; char *limit_clause = NULL; char *machine_clause = NULL; char *query; const char *section; char *name; const char *name_desc; const char *machine; const char *snippet; const char *name_temp; char *slash_ptr; char *m = NULL; int rc; inverse_document_frequency idf = {0, 0}; sqlite3_stmt *stmt; if (args->machine) easprintf(&machine_clause, "AND machine = \'%s\' ", args->machine); /* Register the rank function */ rc = sqlite3_create_function(db, "rank_func", 1, SQLITE_ANY, (void *)&idf, rank_func, NULL, NULL); if (rc != SQLITE_OK) { warnx("Unable to register the ranking function: %s", sqlite3_errmsg(db)); sqlite3_close(db); sqlite3_shutdown(); exit(EXIT_FAILURE); } /* We want to build a query of the form: "select x,y,z from mandb where * mandb match :query [AND (section LIKE '1' OR section LIKE '2' OR...)] * ORDER BY rank DESC..." * NOTES: 1. The portion in square brackets is optional, it will be there * only if the user has specified an option on the command line to search in * one or more specific sections. * 2. I am using LIKE operator because '=' or IN operators do not seem to be * working with the compression option enabled. */ if (args->sec_nums) { char *temp; int i; for (i = 0; i < SECMAX; i++) { if (args->sec_nums[i] == 0) continue; easprintf(&temp, " OR section = \'%d\'", i + 1); if (section_clause) { concat(§ion_clause, temp); free(temp); } else { section_clause = temp; } } if (section_clause) { /* * At least one section requested, add glue for query. */ temp = section_clause; /* Skip " OR " before first term. */ easprintf(§ion_clause, " AND (%s)", temp + 4); free(temp); } } if (args->nrec >= 0) { /* Use the provided number of records and offset */ easprintf(&limit_clause, " LIMIT %d OFFSET %d", args->nrec, args->offset); } if (snippet_args == NULL) { default_snippet_args[0] = ""; default_snippet_args[1] = ""; default_snippet_args[2] = "..."; snippet_args = default_snippet_args; } query = sqlite3_mprintf("SELECT section, name, name_desc, machine," " snippet(mandb, %Q, %Q, %Q, -1, 40 )," " rank_func(matchinfo(mandb, \"pclxn\")) AS rank" " FROM mandb" " WHERE mandb MATCH %Q %s " "%s" " ORDER BY rank DESC" "%s", snippet_args[0], snippet_args[1], snippet_args[2], args->search_str, machine_clause ? machine_clause : "", section_clause ? section_clause : "", limit_clause ? limit_clause : ""); free(machine_clause); free(section_clause); free(limit_clause); if (query == NULL) { *args->errmsg = estrdup("malloc failed"); return -1; } rc = sqlite3_prepare_v2(db, query, -1, &stmt, NULL); if (rc == SQLITE_IOERR) { warnx("Corrupt database. Please rerun makemandb"); sqlite3_free(query); return -1; } else if (rc != SQLITE_OK) { warnx("%s", sqlite3_errmsg(db)); sqlite3_free(query); return -1; } while (sqlite3_step(stmt) == SQLITE_ROW) { section = (const char *) sqlite3_column_text(stmt, 0); name_temp = (const char *) sqlite3_column_text(stmt, 1); name_desc = (const char *) sqlite3_column_text(stmt, 2); machine = (const char *) sqlite3_column_text(stmt, 3); snippet = (const char *) sqlite3_column_text(stmt, 4); if ((slash_ptr = strrchr(name_temp, '/')) != NULL) name_temp = slash_ptr + 1; if (machine && machine[0]) { m = estrdup(machine); easprintf(&name, "%s/%s", lower(m), name_temp); free(m); } else { name = estrdup((const char *) sqlite3_column_text(stmt, 1)); } (args->callback)(args->callback_data, section, name, name_desc, snippet, strlen(snippet)); free(name); } sqlite3_finalize(stmt); sqlite3_free(query); return *(args->errmsg) == NULL ? 0 : -1; }
/* * Build a new environment and ether clear potentially dangerous * variables from the old one or start with a clean slate. * Also adds sudo-specific variables (SUDO_*). */ void rebuild_env(void) { char **old_envp, **ep, *cp, *ps1; char idbuf[MAX_UID_T_LEN]; unsigned int didvar; int reset_home = FALSE; /* * Either clean out the environment or reset to a safe default. */ ps1 = NULL; didvar = 0; env.env_len = 0; env.env_size = 128; old_envp = env.envp; env.envp = emalloc2(env.env_size, sizeof(char *)); #ifdef ENV_DEBUG memset(env.envp, 0, env.env_size * sizeof(char *)); #endif /* Reset HOME based on target user if configured to. */ if (ISSET(sudo_mode, MODE_RUN)) { if (def_always_set_home || ISSET(sudo_mode, MODE_RESET_HOME | MODE_LOGIN_SHELL) || (ISSET(sudo_mode, MODE_SHELL) && def_set_home)) reset_home = TRUE; } if (def_env_reset || ISSET(sudo_mode, MODE_LOGIN_SHELL)) { /* Pull in vars we want to keep from the old environment. */ for (ep = old_envp; *ep; ep++) { int keepit; /* Skip variables with values beginning with () (bash functions) */ if ((cp = strchr(*ep, '=')) != NULL) { if (strncmp(cp, "=() ", 3) == 0) continue; } /* * First check certain variables for '%' and '/' characters. * If no match there, check the keep list. * If nothing matched, we remove it from the environment. */ keepit = matches_env_check(*ep); if (keepit == -1) keepit = matches_env_keep(*ep); /* For SUDO_PS1 -> PS1 conversion. */ if (strncmp(*ep, "SUDO_PS1=", 8) == 0) ps1 = *ep + 5; if (keepit) { /* Preserve variable. */ switch (**ep) { case 'H': if (strncmp(*ep, "HOME=", 5) == 0) SET(didvar, DID_HOME); break; case 'L': if (strncmp(*ep, "LOGNAME=", 8) == 0) SET(didvar, DID_LOGNAME); break; case 'M': if (strncmp(*ep, "MAIL=", 5) == 0) SET(didvar, DID_MAIL); break; case 'P': if (strncmp(*ep, "PATH=", 5) == 0) SET(didvar, DID_PATH); break; case 'S': if (strncmp(*ep, "SHELL=", 6) == 0) SET(didvar, DID_SHELL); break; case 'T': if (strncmp(*ep, "TERM=", 5) == 0) SET(didvar, DID_TERM); break; case 'U': if (strncmp(*ep, "USER="******"USERNAME="******"SHELL", runas_pw->pw_shell, ISSET(didvar, DID_SHELL)); sudo_setenv("LOGNAME", runas_pw->pw_name, ISSET(didvar, DID_LOGNAME)); sudo_setenv("USER", runas_pw->pw_name, ISSET(didvar, DID_USER)); sudo_setenv("USERNAME", runas_pw->pw_name, ISSET(didvar, DID_USERNAME)); } else { if (!ISSET(didvar, DID_SHELL)) sudo_setenv("SHELL", sudo_user.pw->pw_shell, FALSE); if (!ISSET(didvar, DID_LOGNAME)) sudo_setenv("LOGNAME", user_name, FALSE); if (!ISSET(didvar, DID_USER)) sudo_setenv("USER", user_name, FALSE); if (!ISSET(didvar, DID_USERNAME)) sudo_setenv("USERNAME", user_name, FALSE); } /* If we didn't keep HOME, reset it based on target user. */ if (!ISSET(didvar, KEPT_HOME)) reset_home = TRUE; /* * Set MAIL to target user in -i mode or if MAIL is not preserved * from user's environment. */ if (ISSET(sudo_mode, MODE_LOGIN_SHELL) || !ISSET(didvar, KEPT_MAIL)) { cp = _PATH_MAILDIR; if (cp[sizeof(_PATH_MAILDIR) - 2] == '/') easprintf(&cp, "MAIL=%s%s", _PATH_MAILDIR, runas_pw->pw_name); else easprintf(&cp, "MAIL=%s/%s", _PATH_MAILDIR, runas_pw->pw_name); sudo_putenv(cp, ISSET(didvar, DID_MAIL), TRUE); } } else { /* * Copy environ entries as long as they don't match env_delete or * env_check. */ for (ep = old_envp; *ep; ep++) { int okvar; /* Skip variables with values beginning with () (bash functions) */ if ((cp = strchr(*ep, '=')) != NULL) { if (strncmp(cp, "=() ", 3) == 0) continue; } /* * First check variables against the blacklist in env_delete. * If no match there check for '%' and '/' characters. */ okvar = matches_env_delete(*ep) != TRUE; if (okvar) okvar = matches_env_check(*ep) != FALSE; if (okvar) { if (strncmp(*ep, "SUDO_PS1=", 9) == 0) ps1 = *ep + 5; else if (strncmp(*ep, "PATH=", 5) == 0) SET(didvar, DID_PATH); else if (strncmp(*ep, "TERM=", 5) == 0) SET(didvar, DID_TERM); sudo_putenv(*ep, FALSE, FALSE); } } } /* Replace the PATH envariable with a secure one? */ if (def_secure_path && !user_is_exempt()) { sudo_setenv("PATH", def_secure_path, TRUE); SET(didvar, DID_PATH); } /* * Set $USER, $LOGNAME and $USERNAME to target if "set_logname" is not * disabled. We skip this if we are running a login shell (because * they have already been set them) or sudoedit (because we want the * editor to find the user's startup files). */ if (def_set_logname && !ISSET(sudo_mode, MODE_LOGIN_SHELL|MODE_EDIT)) { if (!ISSET(didvar, KEPT_LOGNAME)) sudo_setenv("LOGNAME", runas_pw->pw_name, TRUE); if (!ISSET(didvar, KEPT_USER)) sudo_setenv("USER", runas_pw->pw_name, TRUE); if (!ISSET(didvar, KEPT_USERNAME)) sudo_setenv("USERNAME", runas_pw->pw_name, TRUE); } /* Set $HOME to target user if not preserving user's value. */ if (reset_home) sudo_setenv("HOME", runas_pw->pw_dir, TRUE); /* Provide default values for $TERM and $PATH if they are not set. */ if (!ISSET(didvar, DID_TERM)) sudo_putenv("TERM=unknown", FALSE, FALSE); if (!ISSET(didvar, DID_PATH)) sudo_setenv("PATH", _PATH_STDPATH, FALSE); /* Set PS1 if SUDO_PS1 is set. */ if (ps1 != NULL) sudo_putenv(ps1, TRUE, TRUE); /* Add the SUDO_COMMAND envariable (cmnd + args). */ if (user_args) { easprintf(&cp, "%s %s", user_cmnd, user_args); sudo_setenv("SUDO_COMMAND", cp, TRUE); efree(cp); } else { sudo_setenv("SUDO_COMMAND", user_cmnd, TRUE); } /* Add the SUDO_USER, SUDO_UID, SUDO_GID environment variables. */ sudo_setenv("SUDO_USER", user_name, TRUE); snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_uid); sudo_setenv("SUDO_UID", idbuf, TRUE); snprintf(idbuf, sizeof(idbuf), "%u", (unsigned int) user_gid); sudo_setenv("SUDO_GID", idbuf, TRUE); /* Free old environment. */ efree(old_envp); }
/* * errno_message: Return an error message based on the value of "errno". */ char * errno_message(char *filename) { return (easprintf("%s: %s", filename, strerror(errno))); }
/* * Interpret a POSIX-style -t argument. */ static void posixtypes(char const *type_string) { int nbytes = 0; char *fmt, type, *tmp; struct odformat const *odf; while (*type_string) { odprecede(); switch ((type = *type_string++)) { case 'a': case 'c': nbytes = 1; break; case 'f': if (isupper((unsigned char)*type_string)) { switch(*type_string) { case 'F': nbytes = sizeof(float); break; case 'D': nbytes = sizeof(double); break; case 'L': nbytes = sizeof(long double); break; default: warnx("Bad type-size qualifier '%c'", *type_string); usage(); } type_string++; } else if (isdigit((unsigned char)*type_string)) { nbytes = strtol(type_string, &tmp, 10); type_string = tmp; } else nbytes = 8; break; case 'd': case 'o': case 'u': case 'x': if (isupper((unsigned char)*type_string)) { switch(*type_string) { case 'C': nbytes = sizeof(char); break; case 'S': nbytes = sizeof(short); break; case 'I': nbytes = sizeof(int); break; case 'L': nbytes = sizeof(long); break; default: warnx("Bad type-size qualifier '%c'", *type_string); usage(); } type_string++; } else if (isdigit((unsigned char)*type_string)) { nbytes = strtol(type_string, &tmp, 10); type_string = tmp; } else nbytes = 4; break; default: usage(); } for (odf = odftab; odf->type != 0; odf++) if (odf->type == type && odf->nbytes == nbytes) break; if (odf->type == 0) errx(1, "%c%d: format not supported", type, nbytes); (void)easprintf(&fmt, "%d/%d \"%*s%s \" \"\\n\"", 16 / nbytes, nbytes, 4 * nbytes - odf->minwidth, "", odf->format); add(fmt); } }