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