Esempio n. 1
0
File: logging.c Progetto: CVi/sudo
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);
}
Esempio n. 4
0
/*
 * 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;
}
Esempio n. 5
0
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);
    }
}
Esempio n. 6
0
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(&section_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(&section_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;
}
Esempio n. 8
0
/*
 * 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);
}
Esempio n. 9
0
/*
 * errno_message: Return an error message based on the value of "errno".
 */
char *
errno_message(char *filename)
{
	return (easprintf("%s: %s", filename, strerror(errno)));
}
Esempio n. 10
0
/*
 * 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);
	}
}