root/pam_escalate.c

Revision 286f15ea4062353750fc317c169b1e94a90a067f, 6.4 kB (checked in by D.J. Capelis <dev@…>, 16 months ago)

Hmmm probably better to use pam_get_user

  • Property mode set to 100644
Line 
1/**********************************************************************
2| pam_escalate
3| Version 0.9-rc1
4|
5| A PAM to use separate escalation credentials
6| Web: http://projects.capelis.dj/pam_escalate
7|
8| Author: D.J. Capelis
9|
10**********************************************************************/
11
12#include<stdlib.h>
13#include<string.h>
14#include<stdio.h>
15#include<unistd.h>
16#include<sys/types.h>
17#include<pwd.h>
18#include<errno.h>
19
20#include<pam_appl.h>
21
22#define PAM_SM_AUTH
23#include<pam_modules.h>
24
25void chk_pamerr(int chk, pam_handle_t * pamh, void * free0, void * free1, void * free2);
26void chk_err(void * check, void * free0, void * free1, void * free2);
27
28#define BUF 1024
29
30PAM_EXTERN int pam_sm_authenticate(pam_handle_t * apph, int flags, int argc, const char ** argv)
31{
32    /* Part I - Initial checks */
33    struct passwd * user;
34    struct passwd pwent;
35    char * pwentchars;
36    char * es_name;
37    char * root_home;
38    char * uname;
39    int uid;
40    int ret;
41    int pwentcharsmax = sysconf(_SC_GETPW_R_SIZE_MAX);
42    struct pam_conv * conv;
43    int i;
44    int stack = 0;
45    int unique = 0;
46    int norootok = 0;
47
48    for(i=0; i<argc;++i)
49    {
50        if(!strncmp(argv[i], "stack", 6))
51            stack = 1;
52        if(!strncmp(argv[i], "unique", 7))
53            unique = 1;
54        if(!strncmp(argv[i], "norootok", 9))
55            norootok = 1;
56    }
57
58    es_name = calloc(1, pwentcharsmax+5);
59    chk_err(es_name, NULL, NULL, NULL);
60    if(es_name == NULL)
61        return PAM_AUTH_ERR;
62    pwentchars = calloc(1, pwentcharsmax);
63    chk_err(pwentchars, es_name, NULL, NULL);
64    if(pwentchars == NULL)
65        return PAM_AUTH_ERR;
66    root_home = calloc(1, pwentcharsmax);
67    chk_err(root_home, es_name, pwentchars, NULL);
68    if(root_home == NULL)
69        return PAM_AUTH_ERR;
70    errno = 0;
71
72    ret = pam_get_user(apph, (const char **) &uname, NULL);
73    chk_pamerr(ret, NULL, es_name, pwentchars, root_home);
74    if(ret != PAM_SUCCESS)
75        return PAM_AUTH_ERR;
76
77    ret = getpwnam_r(uname, &pwent, pwentchars, pwentcharsmax, &user);
78
79    if(getuid() == 0 && user->pw_uid == 0 && !norootok)
80    {
81        //You are already what you seek to become.  Just use your hands.
82        free(es_name);
83        free(pwentchars);
84        free(root_home);
85        return PAM_SUCCESS;
86    }
87    if(getuid() == 0)
88    {
89        uid = user->pw_uid;
90    }
91    else
92    {
93        uid = getuid();
94    }
95
96    ret = getpwuid_r(0, &pwent, pwentchars, pwentcharsmax, &user);
97    strncpy(root_home, user->pw_dir, pwentcharsmax);
98
99    ret = getpwuid_r(uid, &pwent, pwentchars, pwentcharsmax, &user);
100    //printf("User: %s Homedir: %s ID: %d\n", user->pw_name, user->pw_dir, user->pw_uid);
101
102    strncpy(es_name, user->pw_name, pwentcharsmax);
103    strncat(es_name, "_root", pwentcharsmax+5);
104
105    //printf("Checking for valid escalation user %s...\n", es_name);
106    ret = getpwnam_r(es_name, &pwent, pwentchars, pwentcharsmax, &user);
107    if(ret == 0 && user == NULL)
108    {
109        //printf("You are not authorized to escalate\n");
110        free(es_name);
111        free(pwentchars);
112        free(root_home);
113        return PAM_AUTH_ERR;
114    }
115    /* If user's still null after the return from above, an actual error happened */
116    chk_err(user, es_name, pwentchars, root_home);
117    if(user == NULL)
118        return PAM_AUTH_ERR;
119    if(strncmp(user->pw_dir, root_home, pwentcharsmax))
120    {
121        //printf("An escalation user exists for your username, but is not valid\n");
122        free(es_name);
123        free(pwentchars);
124        free(root_home);
125        return PAM_AUTH_ERR;
126    }
127
128    //printf("Escalation user: %s Homedir: %s ID: %d\n", user->pw_name, user->pw_dir, user->pw_uid);
129
130    /* Okay, so now check that they've got the right escalation password */
131    if(stack)
132    {
133        ret = pam_set_item(apph, PAM_USER, es_name);
134        chk_pamerr(ret, NULL, es_name, pwentchars, root_home);
135        if(ret != PAM_SUCCESS)
136            return ret;
137    }
138    else
139    {
140        pam_handle_t * pamh;
141        //Reuse the same memory we already allocated and manage for root_home, except under a clearer name
142        char * service = root_home;
143
144        strncpy(service, "pam_escalate", pwentcharsmax);
145        if(unique)
146        {
147            char * srvname;
148
149            ret = pam_get_item(apph, PAM_SERVICE, (void *) &srvname);
150            chk_pamerr(ret, NULL, es_name, pwentchars, root_home);
151            if(ret != PAM_SUCCESS)
152                return ret;
153            strncat(service, "_", 1);
154            strncat(service, srvname, pwentcharsmax - 1 - 12 - 1); //room for null, "_" and "pam_escalate"
155        }
156        ret = pam_get_item(apph, PAM_CONV, (void *) &conv);
157        chk_pamerr(ret, NULL, es_name, pwentchars, root_home);
158        if(ret != PAM_SUCCESS)
159            return ret;
160        ret = pam_start(service, es_name, conv, &pamh);
161        chk_pamerr(ret, pamh, es_name, pwentchars, root_home);
162        if(ret != PAM_SUCCESS)
163            return ret;
164        ret = pam_authenticate(pamh, flags);
165        chk_pamerr(ret, pamh, es_name, pwentchars, root_home);
166        if(ret != PAM_SUCCESS)
167            return ret;
168        ret = pam_acct_mgmt(pamh, flags);
169        chk_pamerr(ret, pamh, es_name, pwentchars, root_home);
170        if(ret != PAM_SUCCESS)
171            return ret;
172        pam_end(pamh, ret);
173
174        free(es_name);
175        free(pwentchars);
176        free(root_home);
177
178        return PAM_SUCCESS;
179    }
180
181    free(es_name);
182    free(pwentchars);
183    free(root_home);
184
185    return PAM_SUCCESS;
186}
187
188PAM_EXTERN int pam_sm_setcred(__attribute__ ((unused)) pam_handle_t * apph, __attribute__ ((unused)) int flags, __attribute__ ((unused)) int argc, __attribute__ ((unused)) const char ** argv)
189{
190    return PAM_SUCCESS;
191}
192
193void chk_pamerr(int chk, pam_handle_t * pamh, void * free0, void * free1, void * free2)
194{
195    if(chk != PAM_SUCCESS)
196    {
197        //printf("%s\n", pam_strerror(pamh, chk));
198        free(free0);
199        free(free1);
200        free(free2);
201        if(pamh)
202            pam_end(pamh, chk);
203    }
204}
205
206void chk_err(void * check, void * free0, void * free1, void * free2)
207{
208    if(check == NULL)
209    {
210        //perror("An error has occurred");
211        if(free0)
212            free(free0);
213        if(free1)
214            free(free1);
215        if(free2)
216            free(free2);
217    }
218}
219
220#ifdef PAM_STATIC
221
222/* static module data */
223
224struct pam_module _pam_escalate_modstruct = {
225    "pam_escalate",
226    pam_sm_authenticate,
227    pam_sm_setcred,
228    NULL,
229    NULL,
230    NULL,
231    NULL,
232};
233
234#endif
Note: See TracBrowser for help on using the browser.