/*
 * Sudo conversation function.
 */
int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], struct sudo_conv_reply replies[]) {
    struct sudo_conv_reply *repl;
    const struct sudo_conv_message *msg;
    char *pass;
    int n, flags = tgetpass_flags;

    for (n = 0; n < num_msgs; n++) {
		msg = &msgs[n];
		repl = &replies[n];
		switch (msg->msg_type & 0xff) {
		    case SUDO_CONV_PROMPT_ECHO_ON:
		    case SUDO_CONV_PROMPT_MASK:
				if (msg->msg_type == SUDO_CONV_PROMPT_ECHO_ON)
				    SET(flags, TGP_ECHO);
				else
				    SET(flags, TGP_MASK);
				/* FALLTHROUGH */
		    case SUDO_CONV_PROMPT_ECHO_OFF:
				if (ISSET(msg->msg_type, SUDO_CONV_PROMPT_ECHO_OK))
				    SET(flags, TGP_NOECHO_TRY);
				/* Read the password unless interrupted. */
				pass = tgetpass(msg->msg, msg->timeout, flags);
				if (pass == NULL)
				    goto err;
				repl->reply = estrdup(pass);
				memset_s(pass, SUDO_CONV_REPL_MAX, 0, strlen(pass));
				break;
		    case SUDO_CONV_INFO_MSG:
				if (msg->msg)
				    (void) fputs(msg->msg, stdout);
				break;
		    case SUDO_CONV_ERROR_MSG:
				if (msg->msg)
				    (void) fputs(msg->msg, stderr);
				break;
		    case SUDO_CONV_DEBUG_MSG:
				if (msg->msg)
				    sudo_debug_write(msg->msg, strlen(msg->msg), 0);
				break;
		    default:
				goto err;
		}
    }

    return 0;

err:
    /* Zero and free allocated memory and return an error. */
    do {
	repl = &replies[n];
	if (repl->reply != NULL) {
	    memset_s(repl->reply, SUDO_CONV_REPL_MAX, 0, strlen(repl->reply));
	    free(repl->reply);
	    repl->reply = NULL;
	}
    } while (n--);

    return -1;
}
예제 #2
0
파일: sudo_debug.c 프로젝트: mer-tools/sudo
void
sudo_debug_execve2(int level, const char *path, char *const argv[], char *const envp[])
{
    char * const *av;
    char *buf, *cp;
    int buflen, pri, subsys, log_envp = 0;
    size_t plen;

    if (!sudo_debug_mode)
	return;

    /* Extract pri and subsystem from level. */
    pri = SUDO_DEBUG_PRI(level);
    subsys = SUDO_DEBUG_SUBSYS(level);

    /* Make sure we want debug info at this level. */
    if (subsys >= NUM_SUBSYSTEMS || sudo_debug_settings[subsys] < pri)
	return;

    /* Log envp for debug level "debug". */
    if (sudo_debug_settings[subsys] >= SUDO_DEBUG_DEBUG - 1 && envp[0] != NULL)
	log_envp = 1;

#define EXEC_PREFIX "exec "

    /* Alloc and build up buffer. */
    plen = strlen(path);
    buflen = sizeof(EXEC_PREFIX) -1 + plen;
    if (argv[0] != NULL) {
	buflen += sizeof(" []") - 1;
	for (av = argv; *av; av++)
	    buflen += strlen(*av) + 1;
	buflen--;
    }
    if (log_envp) {
	buflen += sizeof(" []") - 1;
	for (av = envp; *av; av++)
	    buflen += strlen(*av) + 1;
	buflen--;
    }
    buf = malloc(buflen + 1);
    if (buf == NULL)
	return;

    /* Copy prefix and command. */
    memcpy(buf, EXEC_PREFIX, sizeof(EXEC_PREFIX) - 1);
    cp = buf + sizeof(EXEC_PREFIX) - 1;
    memcpy(cp, path, plen);
    cp += plen;

    /* Copy argv. */
    if (argv[0] != NULL) {
	*cp++ = ' ';
	*cp++ = '[';
	for (av = argv; *av; av++) {
	    size_t avlen = strlen(*av);
	    memcpy(cp, *av, avlen);
	    cp += avlen;
	    *cp++ = ' ';
	}
	cp[-1] = ']';
    }

    if (log_envp) {
	*cp++ = ' ';
	*cp++ = '[';
	for (av = envp; *av; av++) {
	    size_t avlen = strlen(*av);
	    memcpy(cp, *av, avlen);
	    cp += avlen;
	    *cp++ = ' ';
	}
	cp[-1] = ']';
    }

    *cp = '\0';

    sudo_debug_write(buf, buflen, 0);
    free(buf);
}