PAM kbd-int with privsep

Niels Provos provos at citi.umich.edu
Tue Jun 25 20:24:46 EST 2002


On Tue, Jun 25, 2002 at 11:52:55AM +1000, Damien Miller wrote:
> The following is a patch (based on FreeBSD code) which gets kbd-int
> working with privsep. It moves the kbd-int PAM conversation to a child
> process and communicates with it over a socket.
Some comments.  I am pretty tried so I might have missed something.

> +	va_start(ap, fmt);
> +	len = vsnprintf(buf, sizeof(buf), fmt, ap);
> +	va_end(ap);
> +	if (len == -1 || len > sizeof(buf))
> +		fatal("sshpam_send: message too long");
> +	mstr = xstrdup(buf);
> +	if (ctxt->pid != 0)
> +		debug2("to child: %d bytes", len);
> +	r = send(ctxt->sock, mstr, len + 1, MSG_EOR);
> +	free(mstr);
> +	return (r);
> +}
The check on the vsnprintf length is off by one.  It should be
len >= sizeof(buf):

    These functions return the number of characters printed (not
    including the trailing `\0' used to end output to strings), except for
    snprintf() and vsnprintf(), which return the number of characters that
    would have been printed if the size were unlimited (again, not
    including the final `\0').

> +	ctxt = data;
> +	if (n <= 0 || n > PAM_MAX_NUM_MSG)
> +		return (PAM_CONV_ERR);
> +	if ((*resp = calloc(n, sizeof **resp)) == NULL)
> +		return (PAM_BUF_ERR);
This code would be better if the sizeof would be on struct pam_msg or
whatever it is that resp points to.


> +
> +	debug2(__func__);
> +	switch (ctxt->done) {
> +	case 1:
> +		return (0);	
> +	case 0:
> +		break;
> +	default:
> +		return (-1);
> +	}
> +	if (num != 1) {
> +		error("expected one response, got %u", num);
> +		return (-1);
> +	}
> +	sshpam_send(ctxt, "%s", *resp);
> +	switch (sshpam_peek(ctxt)) {
> +	case 'P':
> +	case 'p':
> +		return (1);
> +	case '=':
> +		msg = sshpam_receive(ctxt);
> +		xfree(msg);
> +		ctxt->done = 1;
> +		return (0);
> +	default:
> +		msg = sshpam_receive(ctxt);
> +		if (*msg == '!')
> +			error("%s", msg + 1);
> +		xfree(msg);
> +		ctxt->done = -1;
> +		return (-1);
>  	}
This part could use some comments about what the magic values do.

> +#ifdef USE_PAM
> +    {MONITOR_REQ_PAM_INIT_CTX, 0, mm_answer_sshpam_init_ctx},
> +    {MONITOR_REQ_PAM_START, MON_ONCE, mm_answer_pam_start},
> +    {MONITOR_REQ_PAMQUERY, MON_ISAUTH, mm_answer_sshpamquery},
> +    {MONITOR_REQ_PAMRESPOND, MON_AUTH, mm_answer_sshpamrespond},
> +    {MONITOR_REQ_PAM_FREE_CTX, 0, mm_answer_sshpam_free_ctx},
> +#endif
>      {0, 0, NULL}
>  };
Th INIT and FREE_CTX could you MON_ONCE.   Right? (I do not rally no,
but it looks like it).

>  
> +void
> +mm_sshpam_free_ctx(void *ctxtp)
> +{
> +}
> +
If the child never calls free_ctx, then the monitor code for this
case is not needed.  Or this function needs to be filled in to
free the context correctly.

More eyes should look at the monitor code.

Niels.



More information about the openssh-unix-dev mailing list