9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** @file
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync * VirtualBox External Authentication Library:
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Linux PAM Authentication.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2012 Oracle Corporation
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * available from http://www.virtualbox.org. This file is free software;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * General Public License (GPL) as published by the Free Software
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/* The PAM service name.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * The service name is the name of a file in the /etc/pam.d which contains
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * authentication rules. It is possible to use an existing service
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * name, like "login" for example. But if different set of rules
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * is required, one can create a new file /etc/pam.d/vrdpauth
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * specially for VRDP authentication. Note that the name of the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * service must be lowercase. See PAM documentation for details.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
b8908d384db2324f04a2f68a13e67ea32ebf609avboxsync * The Auth module takes the PAM service name from the
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync * environment variable VBOX_AUTH_PAM_SERVICE. If the variable
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * is not specified, then the 'login' PAM service is used.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#define VBOX_AUTH_PAM_SERVICE_NAME_ENV_OLD "VRDP_AUTH_PAM_SERVICE"
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#define VBOX_AUTH_PAM_SERVICE_NAME_ENV "VBOX_AUTH_PAM_SERVICE"
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#define VBOX_AUTH_PAM_DEFAULT_SERVICE_NAME "login"
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/* The debug log file name.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * If defined, debug messages will be written to the file specified in the
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync * VBOX_AUTH_DEBUG_FILENAME (or deprecated VRDP_AUTH_DEBUG_FILENAME) environment
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync * variable:
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync * export VBOX_AUTH_DEBUG_FILENAME=pam.log
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * The above will cause writing to the pam.log.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#define VBOX_AUTH_DEBUG_FILENAME_ENV_OLD "VRDP_AUTH_DEBUG_FILENAME"
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#define VBOX_AUTH_DEBUG_FILENAME_ENV "VBOX_AUTH_DEBUG_FILENAME"
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/* Dynamic loading of the PAM library.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * If defined, the libpam.so is loaded dynamically.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Enabled by default since it is often required,
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * and does not harm.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#define VBOX_AUTH_USE_PAM_DLLOAD
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#ifdef VBOX_AUTH_USE_PAM_DLLOAD
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/* The name of the PAM library */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# ifdef RT_OS_SOLARIS
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync# define PAM_LIB_NAME "libpam.so.1"
1a06df6ab1717878d43165be3ce300284abf9742vboxsync# elif defined(RT_OS_FREEBSD)
1a06df6ab1717878d43165be3ce300284abf9742vboxsync# define PAM_LIB_NAME "libpam.so"
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# else
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync# define PAM_LIB_NAME "libpam.so.0"
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# endif
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#endif /* VBOX_AUTH_USE_PAM_DLLOAD */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <stdio.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <stdlib.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <stdarg.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <string.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#ifndef RT_OS_FREEBSD
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# include <malloc.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#endif
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <security/pam_appl.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
b8908d384db2324f04a2f68a13e67ea32ebf609avboxsync#include <VBox/VBoxAuth.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#ifdef VBOX_AUTH_USE_PAM_DLLOAD
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#include <dlfcn.h>
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic int (*fn_pam_start)(const char *service_name,
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync const char *user,
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync const struct pam_conv *pam_conversation,
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync pam_handle_t **pamh);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic int (*fn_pam_authenticate)(pam_handle_t *pamh, int flags);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic int (*fn_pam_acct_mgmt)(pam_handle_t *pamh, int flags);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic int (*fn_pam_end)(pam_handle_t *pamh, int pam_status);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic const char * (*fn_pam_strerror)(pam_handle_t *pamh, int errnum);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#else
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#define fn_pam_start pam_start
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#define fn_pam_authenticate pam_authenticate
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#define fn_pam_acct_mgmt pam_acct_mgmt
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#define fn_pam_end pam_end
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#define fn_pam_strerror pam_strerror
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#endif /* VBOX_AUTH_USE_PAM_DLLOAD */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic void debug_printf(const char *fmt, ...)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#if defined(VBOX_AUTH_DEBUG_FILENAME_ENV) || defined(VBOX_AUTH_DEBUG_FILENAME_ENV_OLD)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync va_list va;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync char buffer[1024];
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync const char *filename = NULL;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync va_start(va, fmt);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#if defined(VBOX_AUTH_DEBUG_FILENAME_ENV)
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync filename = getenv (VBOX_AUTH_DEBUG_FILENAME_ENV);
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#endif /* VBOX_AUTH_DEBUG_FILENAME_ENV */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#if defined(VBOX_AUTH_DEBUG_FILENAME_ENV_OLD)
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync if (filename == NULL)
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync {
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync filename = getenv (VBOX_AUTH_DEBUG_FILENAME_ENV_OLD);
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync }
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#endif /* VBOX_AUTH_DEBUG_FILENAME_ENV_OLD */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (filename)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync FILE *f;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync vsnprintf (buffer, sizeof (buffer), fmt, va);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync f = fopen (filename, "ab");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (f != NULL)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync fprintf (f, "%s", buffer);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync fclose (f);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync va_end (va);
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#endif /* VBOX_AUTH_DEBUG_FILENAME_ENV || VBOX_AUTH_DEBUG_FILENAME_ENV_OLD */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#ifdef VBOX_AUTH_USE_PAM_DLLOAD
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic void *gpvLibPam = NULL;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsynctypedef struct _SymMap
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync void **ppfn;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync const char *pszName;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync} SymMap;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic SymMap symmap[] =
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync { (void **)&fn_pam_start, "pam_start" },
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync { (void **)&fn_pam_authenticate, "pam_authenticate" },
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync { (void **)&fn_pam_acct_mgmt, "pam_acct_mgmt" },
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync { (void **)&fn_pam_end, "pam_end" },
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync { (void **)&fn_pam_strerror, "pam_strerror" },
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync { NULL, NULL }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync};
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsyncstatic int auth_pam_init(void)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync SymMap *iter;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync gpvLibPam = dlopen(PAM_LIB_NAME, RTLD_LAZY | RTLD_GLOBAL);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (!gpvLibPam)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync debug_printf("auth_pam_init: dlopen %s failed\n", PAM_LIB_NAME);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return PAM_SYSTEM_ERR;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync iter = &symmap[0];
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync while (iter->pszName != NULL)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync void *pv = dlsym (gpvLibPam, iter->pszName);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (pv == NULL)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync debug_printf("auth_pam_init: dlsym %s failed\n", iter->pszName);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync dlclose(gpvLibPam);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync gpvLibPam = NULL;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return PAM_SYSTEM_ERR;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *iter->ppfn = pv;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync iter++;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return PAM_SUCCESS;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsyncstatic void auth_pam_close(void)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (gpvLibPam)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync dlclose(gpvLibPam);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync gpvLibPam = NULL;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#else
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsyncstatic int auth_pam_init(void)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return PAM_SUCCESS;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsyncstatic void auth_pam_close(void)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync#endif /* VBOX_AUTH_USE_PAM_DLLOAD */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsyncstatic const char *auth_get_pam_service (void)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync const char *service = getenv (VBOX_AUTH_PAM_SERVICE_NAME_ENV);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (service == NULL)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
2c9f3fde0860800f2237593200b107464e67ab70vboxsync service = getenv (VBOX_AUTH_PAM_SERVICE_NAME_ENV_OLD);
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync if (service == NULL)
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync {
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync service = VBOX_AUTH_PAM_DEFAULT_SERVICE_NAME;
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf ("Using PAM service: %s\n", service);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return service;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsynctypedef struct _PamContext
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync char *szUser;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync char *szPassword;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync} PamContext;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsyncstatic int conv (int num_msg, const struct pam_message **msg,
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync struct pam_response **resp, void *appdata_ptr)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync int i;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync struct pam_response *r;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync PamContext *ctx = (PamContext *)appdata_ptr;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (ctx == NULL)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("conv: ctx is NULL\n");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return PAM_CONV_ERR;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("conv: num %d u[%s] p[%d]\n", num_msg, ctx->szUser, ctx->szPassword? strlen (ctx->szPassword): 0);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync r = (struct pam_response *) calloc (num_msg, sizeof (struct pam_response));
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (r == NULL)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return PAM_CONV_ERR;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync for (i = 0; i < num_msg; i++)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync r[i].resp_retcode = 0;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync r[i].resp = strdup (ctx->szPassword);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("conv: %d returning password [%d]\n", i, r[i].resp? strlen (r[i].resp): 0);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync else if (msg[i]->msg_style == PAM_PROMPT_ECHO_ON)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync r[i].resp = strdup (ctx->szUser);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("conv: %d returning name [%s]\n", i, r[i].resp);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync else
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("conv: %d style %d: [%s]\n", i, msg[i]->msg_style, msg[i]->msg? msg[i]->msg: "(null)");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync r[i].resp = NULL;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync *resp = r;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return PAM_SUCCESS;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync/* The entry point must be visible. */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#if defined(_MSC_VER) || defined(__OS2__)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# define DECLEXPORT(type) __declspec(dllexport) type
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#else
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# ifdef VBOX_HAVE_VISIBILITY_HIDDEN
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# define DECLEXPORT(type) __attribute__((visibility("default"))) type
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# else
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# define DECLEXPORT(type) type
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync# endif
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync#endif
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/* prototype to prevent gcc warning */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsyncDECLEXPORT(AuthResult) AUTHCALL AuthEntry(const char *szCaller,
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync PAUTHUUID pUuid,
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync AuthGuestJudgement guestJudgement,
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync const char *szUser,
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync const char *szPassword,
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync const char *szDomain,
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync int fLogon,
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync unsigned clientId);
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsyncDECLEXPORT(AuthResult) AUTHCALL AuthEntry(const char *szCaller,
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync PAUTHUUID pUuid,
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync AuthGuestJudgement guestJudgement,
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync const char *szUser,
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync const char *szPassword,
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync const char *szDomain,
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync int fLogon,
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync unsigned clientId)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync{
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync AuthResult result = AuthResultAccessDenied;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync int rc;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync PamContext ctx;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync struct pam_conv pam_conversation;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync pam_handle_t *pam_handle = NULL;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync /* Only process logon requests. */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync if (!fLogon)
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync return result; /* Return value is ignored by the caller. */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("u[%s], d[%s], p[%d]\n", szUser, szDomain, szPassword? strlen (szPassword): 0);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync ctx.szUser = (char *)szUser;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync ctx.szPassword = (char *)szPassword;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync pam_conversation.conv = conv;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync pam_conversation.appdata_ptr = &ctx;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync rc = auth_pam_init ();
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (rc == PAM_SUCCESS)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("init ok\n");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync rc = fn_pam_start(auth_get_pam_service (), szUser, &pam_conversation, &pam_handle);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (rc == PAM_SUCCESS)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("start ok\n");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync rc = fn_pam_authenticate(pam_handle, 0);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (rc == PAM_SUCCESS)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("auth ok\n");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync rc = fn_pam_acct_mgmt(pam_handle, 0);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (rc == PAM_AUTHINFO_UNAVAIL
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync &&
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync getenv("VBOX_PAM_ALLOW_INACTIVE") != NULL)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("PAM_AUTHINFO_UNAVAIL\n");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync rc = PAM_SUCCESS;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync if (rc == PAM_SUCCESS)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("access granted\n");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync result = AuthResultAccessGranted;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync else
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("pam_acct_mgmt failed %d. %s\n", rc, fn_pam_strerror (pam_handle, rc));
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync else
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("pam_authenticate failed %d. %s\n", rc, fn_pam_strerror (pam_handle, rc));
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync fn_pam_end(pam_handle, rc);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync else
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync debug_printf("pam_start failed %d\n", rc);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync auth_pam_close ();
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync debug_printf("auth_pam_close completed\n");
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync else
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync {
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync debug_printf("auth_pam_init failed %d\n", rc);
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync }
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync return result;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync}
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/* Verify the function prototype. */
45c94fd5bc3ee64a3577f858c7eca5a566601c6fvboxsyncstatic PAUTHENTRY3 gpfnAuthEntry = AuthEntry;