aboutsummaryrefslogtreecommitdiff
path: root/plugin/auth-pam/pamdl.c
blob: aaac2409e7c6f1845f44d70470e40ca37ac8acb4 (plain) (blame)
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#if DLOPEN_PAM
/*
 * If you want to dynamically load libpam using dlopen() or something,
 * then dlopen( ' this shared object ' ); It takes care of exporting
 * the right symbols to any modules loaded by libpam.
 *
 * Modified by JY for use with openvpn-pam-auth
 */

#include <stdio.h>
#include <dlfcn.h>
#include <security/pam_appl.h>
#include <security/_pam_macros.h>

#include "pamdl.h"

static void *libpam_h = NULL;

#define RESOLVE_PAM_FUNCTION(x, y, z, err) \
    { \
        union { const void *tpointer; y (*fn) z ; } fptr; \
	fptr.tpointer = dlsym(libpam_h, #x); real_##x = fptr.fn; \
	if (real_##x == NULL) { \
	    fprintf (stderr, "PAMDL: unable to resolve '%s': %s\n", #x, dlerror()); \
	    return err; \
	} \
    }

int
dlopen_pam (const char *so)
{
  if (libpam_h == NULL)
    {
      libpam_h = dlopen(so, RTLD_GLOBAL|RTLD_NOW);
    }
  return libpam_h != NULL;
}

void
dlclose_pam (void)
{
  if (libpam_h != NULL)
    {
      dlclose(libpam_h);
      libpam_h = NULL;
    }
}

int pam_start(const char *service_name, const char *user,
	      const struct pam_conv *pam_conversation,
	      pam_handle_t **pamh)
{
    int (*real_pam_start)(const char *, const char *,
				 const struct pam_conv *,
				 pam_handle_t **);
    RESOLVE_PAM_FUNCTION(pam_start, int, (const char *, const char *,
					  const struct pam_conv *,
					  pam_handle_t **), PAM_ABORT);
    return real_pam_start(service_name, user, pam_conversation, pamh);
}

int pam_end(pam_handle_t *pamh, int pam_status)
{
    int (*real_pam_end)(pam_handle_t *, int);
    RESOLVE_PAM_FUNCTION(pam_end, int, (pam_handle_t *, int), PAM_ABORT);
    return real_pam_end(pamh, pam_status);
}

int pam_set_item(pam_handle_t *pamh, int item_type, const void *item)
{
    int (*real_pam_set_item)(pam_handle_t *, int, const void *);
    RESOLVE_PAM_FUNCTION(pam_set_item, int,
			 (pam_handle_t *, int, const void *), PAM_ABORT);
    return real_pam_set_item(pamh, item_type, item);
}

int pam_get_item(const pam_handle_t *pamh, int item_type, const void **item)
{
    int (*real_pam_get_item)(const pam_handle_t *, int, const void **);
    RESOLVE_PAM_FUNCTION(pam_get_item, int,
			 (const pam_handle_t *, int, const void **),
			 PAM_ABORT);
    return real_pam_get_item(pamh, item_type, item);
}

int pam_fail_delay(pam_handle_t *pamh, unsigned int musec_delay)
{
    int (*real_pam_fail_delay)(pam_handle_t *, unsigned int);
    RESOLVE_PAM_FUNCTION(pam_fail_delay, int, (pam_handle_t *, unsigned int),
			 PAM_ABORT);
    return real_pam_fail_delay(pamh, musec_delay);
}

typedef const char * const_char_pointer;

const_char_pointer pam_strerror(pam_handle_t *pamh, int errnum)
{
    const_char_pointer (*real_pam_strerror)(pam_handle_t *, int);
    RESOLVE_PAM_FUNCTION(pam_strerror, const_char_pointer,
			 (pam_handle_t *, int), NULL);
    return real_pam_strerror(pamh, errnum);
}

int pam_putenv(pam_handle_t *pamh, const char *name_value)
{
    int (*real_pam_putenv)(pam_handle_t *, const char *);
    RESOLVE_PAM_FUNCTION(pam_putenv, int, (pam_handle_t *, const char *),
			 PAM_ABORT);
    return real_pam_putenv(pamh, name_value);
}

const_char_pointer pam_getenv(pam_handle_t *pamh, const char *name)
{
    const_char_pointer (*real_pam_getenv)(pam_handle_t *, const char *);
    RESOLVE_PAM_FUNCTION(pam_getenv, const_char_pointer,
			 (pam_handle_t *, const char *), NULL);
    return real_pam_getenv(pamh, name);
}

typedef char ** char_ppointer;
char_ppointer pam_getenvlist(pam_handle_t *pamh)
{
    char_ppointer (*real_pam_getenvlist)(pam_handle_t *);
    RESOLVE_PAM_FUNCTION(pam_getenvlist, char_ppointer, (pam_handle_t *),
			 NULL);
    return real_pam_getenvlist(pamh);
}

/* Authentication management */

int pam_authenticate(pam_handle_t *pamh, int flags)
{
    int (*real_pam_authenticate)(pam_handle_t *, int);
    RESOLVE_PAM_FUNCTION(pam_authenticate, int, (pam_handle_t *, int),
			 PAM_ABORT);
    return real_pam_authenticate(pamh, flags);
}

int pam_setcred(pam_handle_t *pamh, int flags)
{
    int (*real_pam_setcred)(pam_handle_t *, int);
    RESOLVE_PAM_FUNCTION(pam_setcred, int, (pam_handle_t *, int), PAM_ABORT);
    return real_pam_setcred(pamh, flags);
}

/* Account Management API's */

int pam_acct_mgmt(pam_handle_t *pamh, int flags)
{
    int (*real_pam_acct_mgmt)(pam_handle_t *, int);
    RESOLVE_PAM_FUNCTION(pam_acct_mgmt, int, (pam_handle_t *, int), PAM_ABORT);
    return real_pam_acct_mgmt(pamh, flags);
}

/* Session Management API's */

int pam_open_session(pam_handle_t *pamh, int flags)
{
    int (*real_pam_open_session)(pam_handle_t *, int);
    RESOLVE_PAM_FUNCTION(pam_open_session, int, (pam_handle_t *, int),
			 PAM_ABORT);
    return real_pam_open_session(pamh, flags);
}

int pam_close_session(pam_handle_t *pamh, int flags)
{
    int (*real_pam_close_session)(pam_handle_t *, int);
    RESOLVE_PAM_FUNCTION(pam_close_session, int, (pam_handle_t *, int),
			 PAM_ABORT);
    return real_pam_close_session(pamh, flags);
}

/* Password Management API's */

int pam_chauthtok(pam_handle_t *pamh, int flags)
{
    int (*real_pam_chauthtok)(pam_handle_t *, int);
    RESOLVE_PAM_FUNCTION(pam_chauthtok, int, (pam_handle_t *, int), PAM_ABORT);
    return real_pam_chauthtok(pamh, flags);
}
#endif