src/authinfo_pipe.c

/* [<][>]
[^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following functions.
  1. sigalrm
  2. pipe_got_pass
  3. pipe_got_sasl

/* $Id: authinfo_pipe.c,v 1.3 2002/03/24 13:38:01 proff Exp $
 * $Copyright$
 */

#include "nglobal.h"

#ifdef AUTHINFO_PIPE

#include "acc.h"
#include "reg.h"

#include "authinfo.h"
#include "authinfo_pipe.h"
#include "network.h"

#include <setjmp.h>

/*
 * pipe authenticator.
 */

EXPORT authenticator pipe_authenticator = {
        authinfo_got_user,
        pipe_got_pass,
#ifdef notyet
        pipe_got_sasl,
#endif
};

/*
 * here are the "user", "pass" and (unsupported) "sasl" routines for an pipe
 * authenticator; note that these are EXPORT so we get prototypes for the
 * "pipe_authenticator" above, which hooks us into authinfo.c ...
 */

/* we use authinfo_got_user() */

/* the alarm handling code here is taken from src/acc.c */

jmp_buf jmp;

static RETSIGTYPE
sigalrm (int sig)
/* [<][>][^][v][top][bottom][index][help] */
{
        longjmp (jmp, 1);
}

EXPORT int pipe_got_pass(char *pass)
/* [<][>][^][v][top][bottom][index][help] */
{
        int i[2];
        volatile int rv = 0;
        int status;
        char *prog;
        RETSIGTYPE (*al)(int) = NULL;
        long al_s;
        pid_t pid;

        if (authinfo_user == NULL) {
                emitf("%d USER required\r\n", NNTP_AUTH_REJECT_VAL);
                return FALSE;
        }
        if (pass && *pass) {
                /*
                 * so, we executed "pipecommand $user" and write the password
                 * at it, and if it exit(0)'s, we are authenticated.  all
                 * other return codes are failure codes.
                 */
                if (socketpair (AF_UNIX, SOCK_STREAM, 0, i) == -1) {
                        loge (("socketpair() failed"));
                        goto done;
                }
                switch ((pid = fork())) {
                case -1:
                        loge(("pipe_got_pass could not fork an authenitcator"));
                        goto done;
                case 0: /* child */
                        prog = strrchr(con->pipeProgram, '/');
                        if (prog == NULL)
                                prog = con->pipeProgram;
                        close(i[1]);
                        dup2(i[0], 0);
                        dup2(i[0], 1);
                        dup2(i[0], 2);
                        execl(con->pipeProgram, prog, authinfo_user, NULL);
                        loge(("execl failed"));
                        _exit(-1);
                }

                /* parent */
                al = signal (SIGALRM, sigalrm);
                al_s = alarm (con->pipeTimeout);
                if (setjmp (jmp) == 1) {
                        kill(9, pid);
                        goto err;
                }

                close(i[0]);
                if (write(i[1], pass, strlen(pass)) != strlen(pass)) {
                        kill(9, pid);
                        (void)wait(NULL);
                        goto err;
                }
                close(i[1]);
                
#ifdef HAVE_WAIT3
                if (wait3(&status, 0, NULL) != pid)
#else
#ifdef HAVE_WAITPID
                if (waitpid(pid, &status, 0) != pid)
#else
#error no wait3 or waitpid for this system
#endif
#endif
                {
                        logen(("wait3/waitpid returns not the authenticator program pid, failing auth."));
                        goto err;
                }
                /* did we go OK? */
                if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
                        rv = 1;

err:
                alarm (0);
                signal (SIGALRM, SIG_DFL);
                if (al)
                {
                        signal(SIGALRM, al);
                        if (al_s > 0)
                                alarm(al_s);
                } else
                        signal (SIGALRM, SIG_DFL);
        }
        
done:
        if (rv != 0) {
                emitf("%d Authentication accepted\r\n", NNTP_AUTH_OK_VAL);
                return TRUE;
        }
        emitf("%d Authentication rejected\r\n", NNTP_AUTH_REJECT_VAL);
        return FALSE;
}

#ifdef notyet
EXPORT int pipe_got_sasl(char *val)
/* [<][>][^][v][top][bottom][index][help] */
{

}
#endif

#endif /* AUTHINFO_PIPE */

/* [<][>][^][v][top][bottom][index][help] */