-
Notifications
You must be signed in to change notification settings - Fork 1
/
auth_aad.c
158 lines (130 loc) · 4.67 KB
/
auth_aad.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
* OpenVPN -- An application to securely tunnel IP networks
* over a single TCP/UDP port, with support for SSL/TLS-based
* session authentication and key exchange,
* packet encryption, packet authentication, and
* packet compression.
*
* Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
* Copyright (C) 2019 CyberNinjas <info@cyberninjas.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include "openvpn-plugin.h"
#include "utils.h" /* openvpn/src/plugins/auth-pam */
#define OPENVPN_PLUGIN_VERSION_MIN 3 /* Require OpenVPN Plugin API v3 */
#define OPENVPN_PLUGIN_STRUCTVER 4
extern int azure_authenticator(const char *user); /* pam_aad.c */
struct plugin_context {
char *aad_auth;
};
void handle_sigchld(int sig)
{
while (waitpid((pid_t) (-1), 0, WNOHANG) > 0) {
/* nonblocking wait (WNOHANG) for any child (-1) to come back */
}
}
static int put_auth_control(const char *path, const char *data)
{
int ret = EXIT_FAILURE;
FILE *f = fopen(path, "w");
if (f) {
if (fprintf(f, "%s", data) == 0)
ret = EXIT_SUCCESS;
fclose(f);
}
return ret;
}
OPENVPN_EXPORT int openvpn_plugin_min_version_required_v1()
{
return OPENVPN_PLUGIN_VERSION_MIN;
}
OPENVPN_EXPORT int
openvpn_plugin_open_v3(const int structver,
struct openvpn_plugin_args_open_in const *args,
struct openvpn_plugin_args_open_return *ret)
{
struct plugin_context *context;
(void) args; /* unused parameter */
/* OPENVPN_PLUGINv3_STRUCTVER defined in openvpn-plugin.h */
if (structver < OPENVPN_PLUGIN_STRUCTVER) {
return OPENVPN_PLUGIN_FUNC_ERROR;
}
/* Allocate the context */
context =
(struct plugin_context *) calloc(1, sizeof(struct plugin_context));
context->aad_auth = "1"; /* dummy value */
/* Intercept the --auth-user-pass-verify callback. */
ret->type_mask =
OPENVPN_PLUGIN_MASK(OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY);
ret->handle = (openvpn_plugin_handle_t) context;
return OPENVPN_PLUGIN_FUNC_SUCCESS;
}
static int azure_auth_handler(struct plugin_context *context,
const char *argv[], const char *envp[])
{
pid_t pid;
struct sigaction sa; /* signal.h */
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART | SA_NOCLDSTOP;
sa.sa_handler = &handle_sigchld;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
return OPENVPN_PLUGIN_FUNC_ERROR;
}
pid = fork();
if (pid < 0) {
/* Fork failed, bail out. */
return OPENVPN_PLUGIN_FUNC_ERROR;
} else if (pid > 0) {
/* We're the parent. Tell openvpn we're deferring. */
return OPENVPN_PLUGIN_FUNC_DEFERRED;
} else {
const char *username = get_env("username", envp),
*auth_control_file = get_env("auth_control_file", envp);
if (azure_authenticator(username) == 0) {
if (put_auth_control
(auth_control_file, (char *) context->aad_auth) == 0)
exit(EXIT_SUCCESS);
}
exit(127);
}
}
OPENVPN_EXPORT int
openvpn_plugin_func_v3(const int structver,
struct openvpn_plugin_args_func_in const *args,
struct openvpn_plugin_args_func_return *ret)
{
struct plugin_context *context =
(struct plugin_context *) args->handle;
/* Check API compatibility -- struct version or higher needed */
if (structver < OPENVPN_PLUGIN_STRUCTVER)
return OPENVPN_PLUGIN_FUNC_ERROR;
switch (args->type) {
case OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY:
return azure_auth_handler(context, args->argv, args->envp);
default:
return OPENVPN_PLUGIN_FUNC_ERROR;
}
}
OPENVPN_EXPORT void openvpn_plugin_close_v1(openvpn_plugin_handle_t handle)
{
struct plugin_context *context = (struct plugin_context *) handle;
free(context);
}