diff options
Diffstat (limited to 'security/openssh/files/patch-auth2-pam.c')
-rw-r--r-- | security/openssh/files/patch-auth2-pam.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/security/openssh/files/patch-auth2-pam.c b/security/openssh/files/patch-auth2-pam.c new file mode 100644 index 000000000000..73605e236db2 --- /dev/null +++ b/security/openssh/files/patch-auth2-pam.c @@ -0,0 +1,336 @@ +--- auth2-pam.c.orig Mon Jun 24 06:54:42 2002 ++++ auth2-pam.c Mon Apr 22 08:25:13 2002 +@@ -0,0 +1,333 @@ ++/*- ++ * Copyright (c) 2002 Networks Associates Technology, Inc. ++ * All rights reserved. ++ * ++ * This software was developed for the FreeBSD Project by ThinkSec AS and ++ * NAI Labs, the Security Research Division of Network Associates, Inc. ++ * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the ++ * DARPA CHATS research program. ++ * ++ * Redistribution and use in source and binary forms, with or without ++ * modification, are permitted provided that the following conditions ++ * are met: ++ * 1. Redistributions of source code must retain the above copyright ++ * notice, this list of conditions and the following disclaimer. ++ * 2. Redistributions in binary form must reproduce the above copyright ++ * notice, this list of conditions and the following disclaimer in the ++ * documentation and/or other materials provided with the distribution. ++ * 3. The name of the author may not be used to endorse or promote ++ * products derived from this software without specific prior written ++ * permission. ++ * ++ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ++ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ++ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ++ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE ++ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ++ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ++ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ++ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ++ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ++ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ++ * SUCH DAMAGE. ++ * ++ * $FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/patch-auth2-pam.c,v 1.1 2002-06-24 21:13:06 dinoex Exp $ ++ */ ++ ++#ifdef USE_PAM ++#include "includes.h" ++RCSID("$FreeBSD: /tmp/pcvs/ports/security/openssh/files/Attic/patch-auth2-pam.c,v 1.1 2002-06-24 21:13:06 dinoex Exp $"); ++ ++#include <security/pam_appl.h> ++ ++#include "auth.h" ++#include "log.h" ++#include "xmalloc.h" ++ ++struct pam_ctxt { ++ char *pam_user; ++ pid_t pam_pid; ++ int pam_sock; ++ int pam_done; ++}; ++ ++static void pam_free_ctx(void *); ++ ++/* ++ * Send message to parent or child. ++ */ ++static int ++pam_send(struct pam_ctxt *ctxt, char *fmt, ...) ++{ ++ va_list ap; ++ char *mstr; ++ size_t len; ++ int r; ++ ++ va_start(ap, fmt); ++ len = vasprintf(&mstr, fmt, ap); ++ va_end(ap); ++ if (mstr == NULL) ++ exit(1); ++ if (ctxt->pam_pid != 0) ++ debug2("to child: %s", mstr); ++ r = send(ctxt->pam_sock, mstr, len + 1, MSG_EOR); ++ free(mstr); ++ return (r); ++} ++ ++/* ++ * Peek at first byte of next message. ++ */ ++static int ++pam_peek(struct pam_ctxt *ctxt) ++{ ++ char ch; ++ ++ if (recv(ctxt->pam_sock, &ch, 1, MSG_PEEK) < 1) ++ return (-1); ++ return (ch); ++} ++ ++/* ++ * Receive a message from parent or child. ++ */ ++static char * ++pam_receive(struct pam_ctxt *ctxt) ++{ ++ char *buf; ++ size_t len; ++ ssize_t rlen; ++ ++ len = 64; ++ buf = NULL; ++ do { ++ len *= 2; ++ buf = xrealloc(buf, len); ++ rlen = recv(ctxt->pam_sock, buf, len, MSG_PEEK); ++ if (rlen < 1) { ++ xfree(buf); ++ return (NULL); ++ } ++ } while (rlen == len); ++ if (recv(ctxt->pam_sock, buf, len, 0) != rlen) { ++ xfree(buf); ++ return (NULL); ++ } ++ if (ctxt->pam_pid != 0) ++ debug2("from child: %s", buf); ++ return (buf); ++} ++ ++/* ++ * Conversation function for child process. ++ */ ++static int ++pam_child_conv(int n, ++ const struct pam_message **msg, ++ struct pam_response **resp, ++ void *data) ++{ ++ struct pam_ctxt *ctxt; ++ int i; ++ ++ 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); ++ for (i = 0; i < n; ++i) { ++ resp[i]->resp_retcode = 0; ++ resp[i]->resp = NULL; ++ switch (msg[i]->msg_style) { ++ case PAM_PROMPT_ECHO_OFF: ++ pam_send(ctxt, "p%s", msg[i]->msg); ++ resp[i]->resp = pam_receive(ctxt); ++ break; ++ case PAM_PROMPT_ECHO_ON: ++ pam_send(ctxt, "P%s", msg[i]->msg); ++ resp[i]->resp = pam_receive(ctxt); ++ break; ++ case PAM_ERROR_MSG: ++ /*pam_send(ctxt, "e%s", msg[i]->msg);*/ ++ break; ++ case PAM_TEXT_INFO: ++ /*pam_send(ctxt, "i%s", msg[i]->msg);*/ ++ break; ++ default: ++ goto fail; ++ } ++ } ++ return (PAM_SUCCESS); ++ fail: ++ while (i) ++ free(resp[--i]); ++ free(*resp); ++ *resp = NULL; ++ return (PAM_CONV_ERR); ++} ++ ++/* ++ * Child process. ++ */ ++static void * ++pam_child(struct pam_ctxt *ctxt) ++{ ++ struct pam_conv pam_conv = { pam_child_conv, ctxt }; ++ pam_handle_t *pamh; ++ int pam_err; ++ ++ pam_err = pam_start("sshd", ctxt->pam_user, &pam_conv, &pamh); ++ if (pam_err != PAM_SUCCESS) ++ goto auth_fail; ++ pam_err = pam_authenticate(pamh, 0); ++ if (pam_err != PAM_SUCCESS) ++ goto auth_fail; ++ pam_send(ctxt, "=OK"); ++ pam_end(pamh, pam_err); ++ exit(0); ++ auth_fail: ++ pam_send(ctxt, "!%s", pam_strerror(pamh, pam_err)); ++ pam_end(pamh, pam_err); ++ exit(0); ++} ++ ++static void * ++pam_init_ctx(Authctxt *authctxt) ++{ ++ struct pam_ctxt *ctxt; ++ int socks[2]; ++ int i; ++ ++ ctxt = xmalloc(sizeof *ctxt); ++ ctxt->pam_user = xstrdup(authctxt->user); ++ ctxt->pam_done = 0; ++ if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, socks) == -1) { ++ error("%s: failed create sockets: %s", ++ __func__, strerror(errno)); ++ xfree(ctxt); ++ return (NULL); ++ } ++ if ((ctxt->pam_pid = fork()) == -1) { ++ error("%s: failed to fork auth-pam child: %s", ++ __func__, strerror(errno)); ++ close(socks[0]); ++ close(socks[1]); ++ xfree(ctxt); ++ return (NULL); ++ } ++ if (ctxt->pam_pid == 0) { ++ /* close everything except our end of the pipe */ ++ ctxt->pam_sock = socks[1]; ++ for (i = 0; i < getdtablesize(); ++i) ++ if (i != ctxt->pam_sock) ++ close(i); ++ pam_child(ctxt); ++ /* not reached */ ++ exit(1); ++ } ++ ctxt->pam_sock = socks[0]; ++ close(socks[1]); ++ return (ctxt); ++} ++ ++static int ++pam_query(void *ctx, char **name, char **info, ++ u_int *num, char ***prompts, u_int **echo_on) ++{ ++ struct pam_ctxt *ctxt = ctx; ++ char *msg; ++ ++ if ((msg = pam_receive(ctxt)) == NULL) ++ return (-1); ++ *name = xstrdup(""); ++ *info = xstrdup(""); ++ *prompts = xmalloc(sizeof(char *)); ++ *echo_on = xmalloc(sizeof(u_int)); ++ switch (*msg) { ++ case 'P': ++ **echo_on = 1; ++ case 'p': ++ *num = 1; ++ **prompts = xstrdup(msg + 1); ++ **echo_on = (*msg == 'P'); ++ break; ++ case '=': ++ *num = 0; ++ **echo_on = 0; ++ ctxt->pam_done = 1; ++ break; ++ case '!': ++ error("%s", msg + 1); ++ default: ++ *num = 0; ++ **echo_on = 0; ++ xfree(msg); ++ ctxt->pam_done = -1; ++ return (-1); ++ } ++ xfree(msg); ++ return (0); ++} ++ ++static int ++pam_respond(void *ctx, u_int num, char **resp) ++{ ++ struct pam_ctxt *ctxt = ctx; ++ char *msg; ++ ++ debug2(__func__); ++ switch (ctxt->pam_done) { ++ case 1: ++ return (0); ++ case 0: ++ break; ++ default: ++ return (-1); ++ } ++ if (num != 1) { ++ error("expected one response, got %u", num); ++ return (-1); ++ } ++ pam_send(ctxt, "%s", *resp); ++ switch (pam_peek(ctxt)) { ++ case 'P': ++ case 'p': ++ return (1); ++ case '=': ++ msg = pam_receive(ctxt); ++ xfree(msg); ++ ctxt->pam_done = 1; ++ return (0); ++ default: ++ msg = pam_receive(ctxt); ++ if (*msg == '!') ++ error("%s", msg + 1); ++ xfree(msg); ++ ctxt->pam_done = -1; ++ return (-1); ++ } ++} ++ ++static void ++pam_free_ctx(void *ctxtp) ++{ ++ struct pam_ctxt *ctxt = ctxtp; ++ int status; ++ ++ close(ctxt->pam_sock); ++ kill(ctxt->pam_pid, SIGHUP); ++ waitpid(ctxt->pam_pid, &status, 0); ++ xfree(ctxt->pam_user); ++ xfree(ctxt); ++} ++ ++KbdintDevice pam_device = { ++ "pam", ++ pam_init_ctx, ++ pam_query, ++ pam_respond, ++ pam_free_ctx ++}; ++ ++#endif /* USE_PAM */ |