1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #ifdef USE_PAM_DLOPEN
6 /*
7  * If you want to dynamically load libpam using dlopen() or something,
8  * then dlopen( ' this shared object ' ); It takes care of exporting
9  * the right symbols to any modules loaded by libpam.
10  *
11  * Modified by JY for use with openvpn-pam-auth
12  */
13 
14 #include <stdio.h>
15 #include <dlfcn.h>
16 #include <security/pam_appl.h>
17 
18 #include "pamdl.h"
19 
20 static void *libpam_h = NULL;
21 
22 #define RESOLVE_PAM_FUNCTION(x, y, z, err) \
23     { \
24         union { const void *tpointer; y(*fn) z; } fptr; \
25         fptr.tpointer = dlsym(libpam_h, #x); real_ ## x = fptr.fn; \
26         if (real_ ## x == NULL) { \
27             fprintf(stderr, "PAMDL: unable to resolve '%s': %s\n", #x, dlerror()); \
28             return err; \
29         } \
30     }
31 
32 int
dlopen_pam(const char * so)33 dlopen_pam(const char *so)
34 {
35     if (libpam_h == NULL)
36     {
37         libpam_h = dlopen(so, RTLD_GLOBAL|RTLD_NOW);
38     }
39     return libpam_h != NULL;
40 }
41 
42 void
dlclose_pam(void)43 dlclose_pam(void)
44 {
45     if (libpam_h != NULL)
46     {
47         dlclose(libpam_h);
48         libpam_h = NULL;
49     }
50 }
51 
52 int
pam_start(const char * service_name,const char * user,const struct pam_conv * pam_conversation,pam_handle_t ** pamh)53 pam_start(const char *service_name, const char *user,
54           const struct pam_conv *pam_conversation,
55           pam_handle_t **pamh)
56 {
57     int (*real_pam_start)(const char *, const char *,
58                           const struct pam_conv *,
59                           pam_handle_t **);
60     RESOLVE_PAM_FUNCTION(pam_start, int, (const char *, const char *,
61                                           const struct pam_conv *,
62                                           pam_handle_t **), PAM_ABORT);
63     return real_pam_start(service_name, user, pam_conversation, pamh);
64 }
65 
66 int
pam_end(pam_handle_t * pamh,int pam_status)67 pam_end(pam_handle_t *pamh, int pam_status)
68 {
69     int (*real_pam_end)(pam_handle_t *, int);
70     RESOLVE_PAM_FUNCTION(pam_end, int, (pam_handle_t *, int), PAM_ABORT);
71     return real_pam_end(pamh, pam_status);
72 }
73 
74 int
pam_set_item(pam_handle_t * pamh,int item_type,const void * item)75 pam_set_item(pam_handle_t *pamh, int item_type, const void *item)
76 {
77     int (*real_pam_set_item)(pam_handle_t *, int, const void *);
78     RESOLVE_PAM_FUNCTION(pam_set_item, int,
79                          (pam_handle_t *, int, const void *), PAM_ABORT);
80     return real_pam_set_item(pamh, item_type, item);
81 }
82 
83 int
pam_get_item(const pam_handle_t * pamh,int item_type,const void ** item)84 pam_get_item(const pam_handle_t *pamh, int item_type, const void **item)
85 {
86     int (*real_pam_get_item)(const pam_handle_t *, int, const void **);
87     RESOLVE_PAM_FUNCTION(pam_get_item, int,
88                          (const pam_handle_t *, int, const void **),
89                          PAM_ABORT);
90     return real_pam_get_item(pamh, item_type, item);
91 }
92 
93 int
pam_fail_delay(pam_handle_t * pamh,unsigned int musec_delay)94 pam_fail_delay(pam_handle_t *pamh, unsigned int musec_delay)
95 {
96     int (*real_pam_fail_delay)(pam_handle_t *, unsigned int);
97     RESOLVE_PAM_FUNCTION(pam_fail_delay, int, (pam_handle_t *, unsigned int),
98                          PAM_ABORT);
99     return real_pam_fail_delay(pamh, musec_delay);
100 }
101 
102 typedef const char *const_char_pointer;
103 
104 const_char_pointer
pam_strerror(pam_handle_t * pamh,int errnum)105 pam_strerror(pam_handle_t *pamh, int errnum)
106 {
107     const_char_pointer (*real_pam_strerror)(pam_handle_t *, int);
108     RESOLVE_PAM_FUNCTION(pam_strerror, const_char_pointer,
109                          (pam_handle_t *, int), NULL);
110     return real_pam_strerror(pamh, errnum);
111 }
112 
113 int
pam_putenv(pam_handle_t * pamh,const char * name_value)114 pam_putenv(pam_handle_t *pamh, const char *name_value)
115 {
116     int (*real_pam_putenv)(pam_handle_t *, const char *);
117     RESOLVE_PAM_FUNCTION(pam_putenv, int, (pam_handle_t *, const char *),
118                          PAM_ABORT);
119     return real_pam_putenv(pamh, name_value);
120 }
121 
122 const_char_pointer
pam_getenv(pam_handle_t * pamh,const char * name)123 pam_getenv(pam_handle_t *pamh, const char *name)
124 {
125     const_char_pointer (*real_pam_getenv)(pam_handle_t *, const char *);
126     RESOLVE_PAM_FUNCTION(pam_getenv, const_char_pointer,
127                          (pam_handle_t *, const char *), NULL);
128     return real_pam_getenv(pamh, name);
129 }
130 
131 typedef char **char_ppointer;
132 char_ppointer
pam_getenvlist(pam_handle_t * pamh)133 pam_getenvlist(pam_handle_t *pamh)
134 {
135     char_ppointer (*real_pam_getenvlist)(pam_handle_t *);
136     RESOLVE_PAM_FUNCTION(pam_getenvlist, char_ppointer, (pam_handle_t *),
137                          NULL);
138     return real_pam_getenvlist(pamh);
139 }
140 
141 /* Authentication management */
142 
143 int
pam_authenticate(pam_handle_t * pamh,int flags)144 pam_authenticate(pam_handle_t *pamh, int flags)
145 {
146     int (*real_pam_authenticate)(pam_handle_t *, int);
147     RESOLVE_PAM_FUNCTION(pam_authenticate, int, (pam_handle_t *, int),
148                          PAM_ABORT);
149     return real_pam_authenticate(pamh, flags);
150 }
151 
152 int
pam_setcred(pam_handle_t * pamh,int flags)153 pam_setcred(pam_handle_t *pamh, int flags)
154 {
155     int (*real_pam_setcred)(pam_handle_t *, int);
156     RESOLVE_PAM_FUNCTION(pam_setcred, int, (pam_handle_t *, int), PAM_ABORT);
157     return real_pam_setcred(pamh, flags);
158 }
159 
160 /* Account Management API's */
161 
162 int
pam_acct_mgmt(pam_handle_t * pamh,int flags)163 pam_acct_mgmt(pam_handle_t *pamh, int flags)
164 {
165     int (*real_pam_acct_mgmt)(pam_handle_t *, int);
166     RESOLVE_PAM_FUNCTION(pam_acct_mgmt, int, (pam_handle_t *, int), PAM_ABORT);
167     return real_pam_acct_mgmt(pamh, flags);
168 }
169 
170 /* Session Management API's */
171 
172 int
pam_open_session(pam_handle_t * pamh,int flags)173 pam_open_session(pam_handle_t *pamh, int flags)
174 {
175     int (*real_pam_open_session)(pam_handle_t *, int);
176     RESOLVE_PAM_FUNCTION(pam_open_session, int, (pam_handle_t *, int),
177                          PAM_ABORT);
178     return real_pam_open_session(pamh, flags);
179 }
180 
181 int
pam_close_session(pam_handle_t * pamh,int flags)182 pam_close_session(pam_handle_t *pamh, int flags)
183 {
184     int (*real_pam_close_session)(pam_handle_t *, int);
185     RESOLVE_PAM_FUNCTION(pam_close_session, int, (pam_handle_t *, int),
186                          PAM_ABORT);
187     return real_pam_close_session(pamh, flags);
188 }
189 
190 /* Password Management API's */
191 
192 int
pam_chauthtok(pam_handle_t * pamh,int flags)193 pam_chauthtok(pam_handle_t *pamh, int flags)
194 {
195     int (*real_pam_chauthtok)(pam_handle_t *, int);
196     RESOLVE_PAM_FUNCTION(pam_chauthtok, int, (pam_handle_t *, int), PAM_ABORT);
197     return real_pam_chauthtok(pamh, flags);
198 }
199 #endif /* ifdef USE_PAM_DLOPEN */
200