|
1 --- src/tcsd/svrside.c 2010-06-09 13:19:00.000000000 -0700 |
|
2 +++ src/tcsd/svrside.c 2012-04-11 14:37:28.993408000 -0700 |
|
3 @@ -27,6 +27,15 @@ |
|
4 #include <arpa/inet.h> |
|
5 #include <errno.h> |
|
6 #include <getopt.h> |
|
7 +#ifdef SOLARIS |
|
8 +#include <priv.h> |
|
9 +#include <fcntl.h> |
|
10 +#endif |
|
11 +#ifndef HAVE_DAEMON |
|
12 +#include <fcntl.h> |
|
13 +#include <syslog.h> |
|
14 +#endif |
|
15 + |
|
16 #include "trousers/tss.h" |
|
17 #include "trousers_types.h" |
|
18 #include "tcs_tsp.h" |
|
19 @@ -44,6 +53,10 @@ |
|
20 static volatile int hup = 0, term = 0; |
|
21 extern char *optarg; |
|
22 |
|
23 +#ifdef SOLARIS |
|
24 +static int get_event_log_from_kernel(void); |
|
25 +#endif |
|
26 + |
|
27 static void |
|
28 tcsd_shutdown(void) |
|
29 { |
|
30 @@ -170,6 +183,10 @@ |
|
31 (void)req_mgr_final(); |
|
32 return result; |
|
33 } |
|
34 +#ifdef SOLARIS |
|
35 + /* Not fatal if this fails */ |
|
36 + (void) get_event_log_from_kernel(); |
|
37 +#endif |
|
38 |
|
39 result = owner_evict_init(); |
|
40 if (result != TSS_SUCCESS) { |
|
41 @@ -208,13 +225,169 @@ |
|
42 } |
|
43 |
|
44 |
|
45 +#ifdef SOLARIS |
|
46 + |
|
47 +extern int get_device_fd(void); |
|
48 + |
|
49 +#define TPM_IOCTL_GETEVTABLE 1 |
|
50 +struct tpm_evtable_ioblk { |
|
51 + uint32_t buflen; |
|
52 + caddr_t buf; |
|
53 +}; |
|
54 + |
|
55 +static int |
|
56 +store_eventlog(char *filename, struct tpm_evtable_ioblk *evlog) |
|
57 +{ |
|
58 + int fd; |
|
59 + int bytes = 0; |
|
60 + |
|
61 + fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0600); |
|
62 + if (fd == -1) { |
|
63 + LogError("Error opening logfile %s: %s", filename, |
|
64 + strerror(errno)); |
|
65 + return (-1); |
|
66 + } |
|
67 + while (bytes < evlog->buflen) { |
|
68 + int n; |
|
69 + n = write(fd, evlog->buf, evlog->buflen - bytes); |
|
70 + if (n == -1 && errno != EAGAIN) { |
|
71 + LogError("Error writing logfile %s: %s", |
|
72 + filename, strerror(errno)); |
|
73 + close(fd); |
|
74 + return (-1); |
|
75 + } |
|
76 + if (n != -1) |
|
77 + bytes += n; |
|
78 + } |
|
79 + close(fd); |
|
80 + |
|
81 + return (0); |
|
82 +} |
|
83 + |
|
84 +static int |
|
85 +get_event_log_from_kernel(void) |
|
86 +{ |
|
87 + int fd = get_device_fd(); |
|
88 + struct tpm_evtable_ioblk ioblk; |
|
89 + |
|
90 + if (fd == -1) |
|
91 + return (-1); |
|
92 + |
|
93 + (void) memset(&ioblk, 0, sizeof (ioblk)); |
|
94 + if (ioctl(fd, TPM_IOCTL_GETEVTABLE, &ioblk)) { |
|
95 + LogDebug("Cannot get event log from kernel: %s", |
|
96 + strerror(errno)); |
|
97 + return (-1); |
|
98 + } |
|
99 + if (ioblk.buflen == 0) |
|
100 + return (0); |
|
101 + |
|
102 + ioblk.buf = calloc(1, ioblk.buflen); |
|
103 + if (ioblk.buf == NULL) { |
|
104 + return (-1); |
|
105 + } |
|
106 + if (ioctl(fd, TPM_IOCTL_GETEVTABLE, &ioblk)) { |
|
107 + free(ioblk.buf); |
|
108 + LogDebug("Cannot get event log from kernel: %s", |
|
109 + strerror(errno)); |
|
110 + return (-1); |
|
111 + } |
|
112 + |
|
113 + return (store_eventlog(tcsd_options.firmware_log_file, &ioblk)); |
|
114 +} |
|
115 + |
|
116 +/* |
|
117 + * For Solaris, make the tcsd privilege aware and drop |
|
118 + * risky privileges if they are not needed. |
|
119 + */ |
|
120 +static int |
|
121 +drop_privs(void) |
|
122 +{ |
|
123 + priv_set_t *myprivs; |
|
124 + int rv; |
|
125 + |
|
126 + /* |
|
127 + * Drop unneeded privs such as fork/exec. |
|
128 + * |
|
129 + * Get "basic" privs and remove the ones we don't want. |
|
130 + */ |
|
131 + if ((myprivs = priv_str_to_set("basic", ",", NULL)) == NULL) { |
|
132 + LogError("priv_str_to_set failed: %s", strerror(errno)); |
|
133 + return (1); |
|
134 + } else { |
|
135 + (void) priv_delset(myprivs, PRIV_PROC_EXEC); |
|
136 + (void) priv_delset(myprivs, PRIV_PROC_FORK); |
|
137 + (void) priv_delset(myprivs, PRIV_FILE_LINK_ANY); |
|
138 + (void) priv_delset(myprivs, PRIV_PROC_INFO); |
|
139 + (void) priv_delset(myprivs, PRIV_PROC_SESSION); |
|
140 + (void) priv_delset(myprivs, PRIV_PROC_SETID); |
|
141 + |
|
142 + /* for auditing */ |
|
143 + (void) priv_addset(myprivs, PRIV_PROC_AUDIT); |
|
144 + |
|
145 + if ((rv = setppriv(PRIV_SET, PRIV_PERMITTED, myprivs))) |
|
146 + return (rv); |
|
147 + if ((rv = setppriv(PRIV_SET, PRIV_LIMIT, myprivs))) |
|
148 + return (rv); |
|
149 + if ((rv = setppriv(PRIV_SET, PRIV_INHERITABLE, myprivs))) |
|
150 + return (rv); |
|
151 + |
|
152 + (void) priv_freeset(myprivs); |
|
153 + } |
|
154 + return (0); |
|
155 +} |
|
156 +#endif /* SOLARIS */ |
|
157 + |
|
158 +#ifndef HAVE_DAEMON |
|
159 +static int |
|
160 +daemon(int nochdir, int noclose) { |
|
161 + int rv, fd; |
|
162 + |
|
163 + if (!noclose) { |
|
164 + closelog(); |
|
165 + closefrom(0); |
|
166 + } |
|
167 + |
|
168 + switch (fork()) { |
|
169 + case -1: /* failure: parent process */ |
|
170 + return (-1); |
|
171 + case 0: /* success: child process */ |
|
172 + break; |
|
173 + default: /* success: parent process */ |
|
174 + exit (0); |
|
175 + } |
|
176 + |
|
177 + /* Create a new SID for the child process */ |
|
178 + if (setsid() == -1) |
|
179 + return (-1); |
|
180 + /* Prevent cwd from being left open and unremovable */ |
|
181 + if (!nochdir) |
|
182 + (void) chdir("/"); |
|
183 + (void) umask(0); |
|
184 + /* Redirect stdin, stdout, and stderr to /dev/null */ |
|
185 + if (!noclose && (fd = open("/dev/null", O_RDWR, 0)) != -1) { |
|
186 + (void) dup2(fd, STDIN_FILENO); |
|
187 + (void) dup2(fd, STDOUT_FILENO); |
|
188 + (void) dup2(fd, STDERR_FILENO); |
|
189 + if (fd > 2) |
|
190 + (void)close (fd); |
|
191 + } |
|
192 + return (0); |
|
193 +} |
|
194 +#endif /* !HAVE_DAEMON */ |
|
195 + |
|
196 int |
|
197 main(int argc, char **argv) |
|
198 { |
|
199 - struct sockaddr_in serv_addr, client_addr; |
|
200 + typedef union { |
|
201 + struct sockaddr_in in; |
|
202 + struct sockaddr_un un; |
|
203 + } sockaddr_un_in_t; |
|
204 + sockaddr_un_in_t serv_addr, client_addr; |
|
205 + int rv; |
|
206 TSS_RESULT result; |
|
207 int sd, newsd, c, option_index = 0; |
|
208 - unsigned client_len; |
|
209 + unsigned client_len, serv_len; |
|
210 char *hostname = NULL; |
|
211 struct passwd *pwd; |
|
212 struct hostent *client_hostent = NULL; |
|
213 @@ -245,26 +418,49 @@ |
|
214 if ((result = tcsd_startup())) |
|
215 return (int)result; |
|
216 |
|
217 - sd = socket(AF_INET, SOCK_STREAM, 0); |
|
218 - if (sd < 0) { |
|
219 - LogError("Failed socket: %s", strerror(errno)); |
|
220 - return -1; |
|
221 - } |
|
222 + if (tcsd_options.port == 0) { /* UNIX Domain socket */ |
|
223 + /* Use UNIX Domain socket instead of TCP/IP socket */ |
|
224 + sd = socket(AF_UNIX, SOCK_STREAM, 0); |
|
225 + if (sd < 0) { |
|
226 + LogError("Failed socket: %s", strerror(errno)); |
|
227 + return -1; |
|
228 + } |
|
229 + |
|
230 + memset(&serv_addr, 0, sizeof (serv_addr)); |
|
231 + serv_addr.un.sun_family = AF_UNIX; |
|
232 + strncpy(serv_addr.un.sun_path, TCSD_DEFAULT_SOCKET, |
|
233 + sizeof (serv_addr.un.sun_path)); |
|
234 + |
|
235 + } else { /* TCP socket */ |
|
236 + sd = socket(AF_INET, SOCK_STREAM, 0); |
|
237 + if (sd < 0) { |
|
238 + LogError("Failed socket: %s", strerror(errno)); |
|
239 + return -1; |
|
240 + } |
|
241 |
|
242 - memset(&serv_addr, 0, sizeof (serv_addr)); |
|
243 - serv_addr.sin_family = AF_INET; |
|
244 - serv_addr.sin_port = htons(tcsd_options.port); |
|
245 - |
|
246 - /* If no remote_ops are defined, restrict connections to localhost |
|
247 - * only at the socket. */ |
|
248 - if (tcsd_options.remote_ops[0] == 0) |
|
249 - serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|
250 - else |
|
251 - serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); |
|
252 - |
|
253 - c = 1; |
|
254 - setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &c, sizeof(c)); |
|
255 - if (bind(sd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0) { |
|
256 + memset(&serv_addr, 0, sizeof (serv_addr)); |
|
257 + serv_addr.in.sin_family = AF_INET; |
|
258 + serv_addr.in.sin_port = htons(tcsd_options.port); |
|
259 + |
|
260 + /* If no remote_ops are defined, restrict connections to localhost |
|
261 + * only at the socket. */ |
|
262 + if (tcsd_options.remote_ops[0] == 0) |
|
263 + serv_addr.in.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|
264 + else |
|
265 + serv_addr.in.sin_addr.s_addr = htonl(INADDR_ANY); |
|
266 + |
|
267 + c = 1; |
|
268 + setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &c, sizeof(c)); |
|
269 + } |
|
270 + |
|
271 + if (tcsd_options.port == 0) { /* UNIX Domain socket */ |
|
272 + serv_len = (unsigned)sizeof(serv_addr.un); |
|
273 + client_len = (unsigned)sizeof(client_addr.un); |
|
274 + } else { /* TCP socket */ |
|
275 + serv_len = (unsigned)sizeof(serv_addr.in); |
|
276 + client_len = (unsigned)sizeof(client_addr.in); |
|
277 + } |
|
278 + if (bind(sd, (struct sockaddr *) &serv_addr, serv_len) < 0) { |
|
279 LogError("Failed bind: %s", strerror(errno)); |
|
280 return -1; |
|
281 } |
|
282 @@ -285,7 +481,6 @@ |
|
283 LogError("Failed listen: %s", strerror(errno)); |
|
284 return -1; |
|
285 } |
|
286 - client_len = (unsigned)sizeof(client_addr); |
|
287 |
|
288 if (getenv("TCSD_FOREGROUND") == NULL) { |
|
289 if (daemon(0, 0) == -1) { |
|
290 @@ -295,6 +490,12 @@ |
|
291 } |
|
292 } |
|
293 |
|
294 +#ifdef SOLARIS |
|
295 + /* For Solaris, drop privileges for security. */ |
|
296 + if ((rv = drop_privs())) |
|
297 + return (rv); |
|
298 +#endif /* SOLARIS */ |
|
299 + |
|
300 LogInfo("%s: TCSD up and running.", PACKAGE_STRING); |
|
301 do { |
|
302 newsd = accept(sd, (struct sockaddr *) &client_addr, &client_len); |
|
303 @@ -314,20 +515,22 @@ |
|
304 } |
|
305 LogDebug("accepted socket %i", newsd); |
|
306 |
|
307 - if ((client_hostent = gethostbyaddr((char *) &client_addr.sin_addr, |
|
308 - sizeof(client_addr.sin_addr), |
|
309 + if (tcsd_options.port != 0) { /* TCP socket */ |
|
310 + if ((client_hostent = gethostbyaddr((char *) &client_addr.in.sin_addr, |
|
311 + sizeof(client_addr.in.sin_addr), |
|
312 AF_INET)) == NULL) { |
|
313 - char buf[16]; |
|
314 - uint32_t addr = htonl(client_addr.sin_addr.s_addr); |
|
315 + char buf[16]; |
|
316 + uint32_t addr = htonl(client_addr.in.sin_addr.s_addr); |
|
317 |
|
318 - snprintf(buf, 16, "%d.%d.%d.%d", (addr & 0xff000000) >> 24, |
|
319 - (addr & 0x00ff0000) >> 16, (addr & 0x0000ff00) >> 8, |
|
320 - addr & 0x000000ff); |
|
321 + snprintf(buf, 16, "%d.%d.%d.%d", (addr & 0xff000000) >> 24, |
|
322 + (addr & 0x00ff0000) >> 16, (addr & 0x0000ff00) >> 8, |
|
323 + addr & 0x000000ff); |
|
324 |
|
325 - LogWarn("Host name for connecting IP %s could not be resolved", buf); |
|
326 - hostname = strdup(buf); |
|
327 - } else { |
|
328 - hostname = strdup(client_hostent->h_name); |
|
329 + LogWarn("Host name for connecting IP %s could not be resolved", buf); |
|
330 + hostname = strdup(buf); |
|
331 + } else { |
|
332 + hostname = strdup(client_hostent->h_name); |
|
333 + } |
|
334 } |
|
335 |
|
336 tcsd_thread_create(newsd, hostname); |