1 /* author: klacke@hyber.org                                  */
2 /* purpose, make us run under a different username           */
3 /*          as well as iface to some other idiotic syscalls  */
4 /*          FIXME replace this entirely with a proper        */
5 /*          posix interface                                  */
6 
7 
8 #include <unistd.h>
9 #include <sys/types.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <pwd.h>
14 #include <stdlib.h>
15 
16 #include "erl_driver.h"
17 
18 
19 
20 static ErlDrvData setuid_start(ErlDrvPort port, char *buf);
21 static void setuid_stop(ErlDrvData drv_data);
22 
23 static ErlDrvEntry setuid_driver_entry;
24 
25 
26 /* buf is the name of the intented user */
setuid_start(ErlDrvPort port,char * buf)27 static ErlDrvData setuid_start(ErlDrvPort port, char *buf)
28 {
29     char *t;
30     char xbuf[BUFSIZ];
31     struct passwd *pe;
32 
33     if ((t = strchr(buf, ' ')) == NULL)
34         return (ErlDrvData) -1;
35 
36     /* Rewind pw mapping */
37     setpwent();
38 
39     t++;
40     switch (*t++) {
41     case 's':  /* setuid */
42         while ((pe = getpwent())) {
43             if (strcmp(pe->pw_name , t) == 0) {
44                 if ((setuid(pe->pw_uid)  != 0) ||
45                     (setreuid(pe->pw_uid, pe->pw_uid) != 0)) {
46                     return (ErlDrvData) -1;
47                 }
48                 sprintf(xbuf, "ok %u", (unsigned)pe->pw_uid);
49                 endpwent();
50                 driver_output(port,xbuf, strlen(xbuf));
51                 return (ErlDrvData) port;
52             }
53         }
54         endpwent();
55         break;
56     case 'n': {
57         int uid = atoi(t);
58         while ((pe = getpwent())) {
59             if (pe->pw_uid == uid) {
60                 sprintf(xbuf, "ok %s", pe->pw_name);
61                 endpwent();
62                 driver_output(port,xbuf, strlen(xbuf));
63                 return (ErlDrvData) port;
64             }
65         }
66         endpwent();
67         driver_output(port, "ok -", 4);
68         return (ErlDrvData) port;
69     }
70     case 'g':   /* getuid */
71         sprintf(xbuf, "ok %u", (unsigned)getuid());
72         driver_output(port,xbuf, strlen(xbuf));
73         return (ErlDrvData) port;
74     case 'u':
75         while ((pe = getpwent())) {
76             if (strcmp(pe->pw_name , t) == 0) {
77                 sprintf(xbuf, "ok %u", (unsigned)pe->pw_uid);
78                 endpwent();
79                 driver_output(port,xbuf, strlen(xbuf));
80                 return (ErlDrvData) port;
81             }
82         }
83         endpwent();
84         break;
85     case 'h':
86         while ((pe = getpwent())) {
87             if (strcmp(pe->pw_name , t) == 0) {
88                 sprintf(xbuf, "ok %s", pe->pw_dir);
89                 endpwent();
90                 driver_output(port,xbuf, strlen(xbuf));
91                 return (ErlDrvData) port;
92             }
93         }
94         endpwent();
95         break;
96     }
97     // In any case return error(?) for non void function
98     return (ErlDrvData) -1;
99 
100 
101 }
102 
103 
setuid_stop(ErlDrvData drv_data)104 static void setuid_stop(ErlDrvData drv_data)
105 {
106 }
107 
108 
109 
110 
111 /*
112  * Initialize and return a driver entry struct
113  */
114 
115 
116 
117 
DRIVER_INIT(setuid_drv)118 DRIVER_INIT(setuid_drv)
119 {
120     setuid_driver_entry.init            = NULL;   /* Not used */
121     setuid_driver_entry.start           = setuid_start;
122     setuid_driver_entry.stop            = setuid_stop;
123     setuid_driver_entry.output          = NULL;
124     setuid_driver_entry.ready_input     = NULL;
125     setuid_driver_entry.ready_output    = NULL;
126     setuid_driver_entry.driver_name     = "setuid_drv";
127     setuid_driver_entry.finish          = NULL;
128     setuid_driver_entry.handle          = NULL;
129     setuid_driver_entry.control         = NULL;
130     setuid_driver_entry.timeout         = NULL;
131     setuid_driver_entry.outputv         = NULL;
132     setuid_driver_entry.ready_async     = NULL;
133     setuid_driver_entry.flush           = NULL;
134     setuid_driver_entry.call            = NULL;
135     setuid_driver_entry.extended_marker = ERL_DRV_EXTENDED_MARKER;
136     setuid_driver_entry.major_version   = ERL_DRV_EXTENDED_MAJOR_VERSION;
137     setuid_driver_entry.minor_version   = ERL_DRV_EXTENDED_MINOR_VERSION;
138     setuid_driver_entry.driver_flags    = 0;
139     setuid_driver_entry.handle2         = NULL;
140     setuid_driver_entry.process_exit    = NULL;
141     setuid_driver_entry.stop_select     = NULL;
142     return (ErlDrvEntry*) &setuid_driver_entry;
143 }
144 
145 
146