33#include <security/pam_appl.h>
45#include <sys/socket.h>
55#define DEBUG(verb) ((verb) >= 4)
58#define COMMAND_VERIFY 0
62#define RESPONSE_INIT_SUCCEEDED 10
63#define RESPONSE_INIT_FAILED 11
64#define RESPONSE_VERIFY_SUCCEEDED 12
65#define RESPONSE_VERIFY_FAILED 13
66#define RESPONSE_DEFER 14
101#define N_NAME_VALUE 16
142 if (size ==
sizeof(
c))
158 if (size ==
sizeof(
c))
219#if defined(__APPLE__) && defined(__clang__)
220#pragma clang diagnostic push
221#pragma clang diagnostic ignored "-Wdeprecated-declarations"
227#if defined(__APPLE__) && defined(__clang__)
228#pragma clang diagnostic pop
255 for (
i = 3;
i <= 100; ++
i)
371 const char **envp =
args->envp;
376 fprintf(
stderr,
"AUTH-PAM: This plugin is incompatible with the running version of OpenVPN\n");
429 const int base = base_parms + i * 2;
439 const char *verb_string =
get_env(
"verb", envp);
442 context->verb = atoi(verb_string);
450 if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
476 if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0)
485 context->foreground_fd = fd[0];
530 const char *username =
get_env(
"username", envp);
531 const char *password =
get_env(
"password", envp);
532 const char *common_name =
get_env(
"common_name", envp) ?
get_env(
"common_name", envp) :
"";
533 const char *remote =
get_env(
"untrusted_ip6", envp);
537 remote =
get_env(
"untrusted_ip", envp);
548 const char *auth_control_file =
get_env(
"auth_control_file", envp);
549 const char *deferred_auth_pam =
get_env(
"deferred_auth_pam", envp);
550 if (auth_control_file != NULL && deferred_auth_pam != NULL)
560 auth_control_file =
"";
563 if (username && strlen(username) > 0 && password)
609 if (
context->foreground_fd >= 0)
618 if (
context->background_pid > 0)
620 waitpid(
context->background_pid, NULL, 0);
648my_conv(
int n,
const struct pam_message **msg_array,
649 struct pam_response **response_array,
void *appdata_ptr)
652 struct pam_response *aresp;
654 int ret = PAM_SUCCESS;
656 *response_array = NULL;
658 if (n <= 0 || n > PAM_MAX_NUM_MSG)
660 return (PAM_CONV_ERR);
662 if ((aresp = calloc(n,
sizeof *aresp)) == NULL)
664 return (PAM_BUF_ERR);
668 for (i = 0; i < n; ++i)
670 const struct pam_message *
msg = msg_array[i];
671 aresp[i].resp_retcode = 0;
672 aresp[i].resp = NULL;
678 msg->msg ?
msg->msg :
"NULL",
689 for (
j = 0;
j < list->
len; ++
j)
744 switch (
msg->msg_style)
648my_conv(
int n,
const struct pam_message **msg_array, {
…}
793 struct pam_conv conv;
794 pam_handle_t *pamh = NULL;
801 conv.appdata_ptr = (
void *)up;
803 if (
status == PAM_SUCCESS)
811 if (
status == PAM_SUCCESS)
813 status = pam_authenticate(pamh, 0);
815 if (
status == PAM_SUCCESS)
817 status = pam_acct_mgmt(pamh, 0);
819 if (
status == PAM_SUCCESS)
829 pam_strerror(pamh,
status));
869 waitpid(p1, NULL, 0);
893 int ac_fd = open( ac_file_name, O_WRONLY );
902 if (
write( ac_fd, pam_success ?
"1" :
"0", 1 ) != 1)
909 up->
username, pam_success ?
"succeeded" :
"rejected" );
920 char ac_file_name[PATH_MAX];
923 static const char pam_so[] =
"libpam.so";
938 if (!dlopen_pam(pam_so))
962 memset(&up, 0,
sizeof(up));
980 ||
recv_string(fd, ac_file_name,
sizeof(ac_file_name)) == -1
1004 if (strlen(ac_file_name) > 0)
1050#ifdef USE_PAM_DLOPEN
OPENVPN_EXPORT int openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
This function is called by OpenVPN each time the OpenVPN reaches a point where plug-in calls should h...
static void set_signals(void)
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
This cleans up the last part of the plug-in, allows it to shut down cleanly and release the plug-in g...
static plugin_log_t plugin_log
static int pam_auth(const char *service, const struct user_pass *up)
static int name_value_match(const char *query, const char *match)
static int send_string(int fd, const char *string)
#define RESPONSE_INIT_SUCCEEDED
static plugin_secure_memzero_t plugin_secure_memzero
static int my_conv(int n, const struct pam_message **msg_array, struct pam_response **response_array, void *appdata_ptr)
static void do_deferred_pam_auth(int fd, const char *ac_file_name, const char *service, const struct user_pass *up)
#define RESPONSE_INIT_FAILED
static plugin_base64_decode_t plugin_base64_decode
static void pam_server(int fd, const char *service, int verb, const struct name_value_list *name_value_list)
#define RESPONSE_VERIFY_FAILED
OPENVPN_EXPORT void openvpn_plugin_abort_v1(openvpn_plugin_handle_t handle)
static int recv_control(int fd)
static int send_control(int fd, int code)
static void close_fds_except(int keep)
OPENVPN_EXPORT int openvpn_plugin_open_v3(const int v3structver, struct openvpn_plugin_args_open_in const *args, struct openvpn_plugin_args_open_return *ret)
This function is called when OpenVPN loads the plug-in.
#define RESPONSE_VERIFY_SUCCEEDED
static int recv_string(int fd, char *buffer, int len)
static void split_scrv1_password(struct user_pass *up)
int string_array_len(const char **array)
int daemon(int nochdir, int noclose)
static void daemonize(const char *envp[])
static SERVICE_STATUS status
static SERVICE_STATUS_HANDLE service
#define OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY
void * openvpn_plugin_handle_t
#define OPENVPN_PLUGIN_MASK(x)
void(* plugin_log_t)(openvpn_plugin_log_flags_t flags, const char *plugin_name, const char *format,...) _ovpn_chk_fmt(3
#define OPENVPN_PLUGIN_FUNC_DEFERRED
#define OPENVPN_PLUGIN_FUNC_SUCCESS
void(*) typedef void(*) typedef void(* plugin_secure_memzero_t)(void *data, size_t len)
Export of secure_memzero() to be used inside plug-ins.
#define OPENVPN_PLUGIN_FUNC_ERROR
int(* plugin_base64_decode_t)(const char *str, void *data, int size)
Export of openvpn_base64_decode() to be used inside plug-ins.
static const char * get_env(const char *name, const char *envp[])
Wrapper structure for dynamically allocated memory.
Contains all state information for one tunnel.
struct name_value data[N_NAME_VALUE]
Arguments used to transport variables to the plug-in.
struct openvpn_plugin_callbacks * callbacks
Arguments used to transport variables from the plug-in back to the OpenVPN process.
openvpn_plugin_handle_t handle
plugin_base64_decode_t plugin_base64_decode
plugin_secure_memzero_t plugin_secure_memzero
const struct name_value_list * name_value_list
char password[USER_PASS_LEN]
char remote[INET6_ADDRSTRLEN]
char username[USER_PASS_LEN]
char * searchandreplace(const char *tosearch, const char *searchfor, const char *replacewith)
Read 'tosearch', replace all occurrences of 'searchfor' with 'replacewith' and return a pointer to th...